From b008ad9766f8df021b272a54ca38f5079f8995cf Mon Sep 17 00:00:00 2001 From: chentianrui Date: Wed, 28 Aug 2024 09:39:57 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=86=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/engine/loaders/__init__.py | 26 +++---- backend/app/engine/loaders/db.py | 94 +++++++------------------- backend/app/engine/prompt.py | 12 ++-- 3 files changed, 44 insertions(+), 88 deletions(-) diff --git a/backend/app/engine/loaders/__init__.py b/backend/app/engine/loaders/__init__.py index a220170..241f68a 100644 --- a/backend/app/engine/loaders/__init__.py +++ b/backend/app/engine/loaders/__init__.py @@ -1,24 +1,26 @@ import logging - -import yaml -from app.engine.loaders.db import DBLoaderConfig, get_db_documents +# import yaml from app.engine.loaders.file import FileLoaderConfig, get_file_documents from app.engine.loaders.web import WebLoaderConfig, get_web_documents logger = logging.getLogger(__name__) - -def load_configs(): - with open("config/loaders.yaml") as f: - configs = yaml.safe_load(f) - return configs +# 注释掉 load_configs 函数 +# def load_configs(): +# with open("config/loaders.yaml") as f: +# configs = yaml.safe_load(f) +# return configs def get_documents(): documents = [] - config = load_configs() - if config is None or len(config.items()) == 0: - return documents + # 注释掉对 load_configs 的调用 + # config = load_configs() + # if config is None or len(config.items()) == 0: + # return documents + + # 使用一个空的 config 替代原有的配置加载逻辑 + config = {} for loader_type, loader_config in config.items(): logger.info( @@ -31,8 +33,6 @@ def get_documents(): document = get_file_documents(FileLoaderConfig(**loader_config)) case "web": document = get_web_documents(WebLoaderConfig(**loader_config)) - case "db": - document = get_db_documents(configs=[DBLoaderConfig(**cfg) for cfg in loader_config]) case _: raise ValueError(f"Invalid loader type: {loader_type}") documents.extend(document) diff --git a/backend/app/engine/loaders/db.py b/backend/app/engine/loaders/db.py index d6310e2..0289fb5 100644 --- a/backend/app/engine/loaders/db.py +++ b/backend/app/engine/loaders/db.py @@ -1,18 +1,12 @@ import logging from typing import Any, List, Optional -from llama_index.core import SQLDatabase, Document -from llama_index.core.objects import SQLTableSchema -from llama_index.core.readers.base import BaseReader -from llama_index.readers.database import DatabaseReader +from llama_index.core import Document from pydantic import BaseModel -from sqlalchemy import create_engine -from sqlalchemy import text -from sqlalchemy.engine import Engine logger = logging.getLogger(__name__) -class CustomDatabaseReader(BaseReader): +class CustomDatabaseReader: """Simple Database reader. Concatenates each row into Document used by LlamaIndex. @@ -45,8 +39,8 @@ class CustomDatabaseReader(BaseReader): def __init__( self, - sql_database: Optional[SQLDatabase] = None, - engine: Optional[Engine] = None, + sql_database: Optional[Any] = None, + engine: Optional[Any] = None, uri: Optional[str] = None, scheme: Optional[str] = None, host: Optional[str] = None, @@ -58,50 +52,24 @@ class CustomDatabaseReader(BaseReader): **kwargs: Any, ) -> None: """Initialize with parameters.""" - if sql_database: - self.sql_database = sql_database - elif engine: - self.sql_database = SQLDatabase(engine, *args, **kwargs) - elif uri: - self.uri = uri - self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs) - elif scheme and host and port and user and password and dbname: - uri = f"{scheme}://{user}:{password}@{host}:{port}/{dbname}" - self.uri = uri - self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs) - else: - raise ValueError( - "You must provide either a SQLDatabase, " - "a SQL Alchemy Engine, a valid connection URI, or a valid " - "set of credentials." - ) + # Setting the database-related properties to None + self.sql_database = None + self.uri = None - def load_data(self, query: str) -> List[Document]: - """Query and load data from the Database, returning a list of Documents. + def load_data(self, query: str, explanation: str) -> List[Document]: + """Simulate loading data without a database connection. Args: - query (str): Query parameter to filter tables and rows. + query (str): Query parameter (not used). + explanation (str): Explanation to be included in the document. Returns: List[Document]: A list of Document objects. """ - dco_str = "" - with self.sql_database.engine.connect() as connection: - if query is None: - raise ValueError("A query parameter is necessary to filter the data") - else: - result = connection.execute(text(query)) - - dco_str = ", ".join( - [f"{entry}" for entry in result.keys()] - ) - - for item in result.fetchall(): - # fetch each item - record_str = ", ".join( - [f"{entry}" for col, entry in zip(result.keys(), item)] - ) - dco_str += record_str + "\n" + dco_str = explanation + "\n" + # Simulate data without querying a real database + dco_str += "Simulated column1, Simulated column2\n" + dco_str += "Simulated data1, Simulated data2\n" doc = Document(text=dco_str) doc.metadata["name"] = query @@ -111,7 +79,7 @@ class CustomDatabaseReader(BaseReader): class DBLoaderConfig(BaseModel): uri: str - queries: List[str] + queries: List[dict] def get_db_documents(configs: list[DBLoaderConfig]): docs = [] @@ -123,33 +91,17 @@ def get_db_documents(configs: list[DBLoaderConfig]): return docs metadata = { - #'file_name':'', - 'file_type':'application/booway.document.zj', - #'file_path':'', - #'file_size':'', - #'creation_date':'', - #'last_modified_date':'', + 'file_type': 'application/booway.document.zj', } - #from llama_index.readers.database import DatabaseReader for entry in configs: - engine = create_engine(entry.uri) - sql_database = SQLDatabase(engine) - - # table_schema_objs = makeDescriptionByEngine(sql_database) - # table_node_mapping = SQLTableNodeMapping(sql_database) - # - # nodes = table_node_mapping.to_nodes(table_schema_objs) - # for node in nodes: - # node.metadata.update(metadata) - # - # docs.extend(nodes) - - queries = entry.queries or [] - loader = CustomDatabaseReader(sql_database) - for query in queries: + # Skipping the database connection part + loader = CustomDatabaseReader() + for query_dict in entry.queries: + query = query_dict.get("sql", "") + explanation = query_dict.get("explanation", "") logger.info(f"Loading data from database with query: {query}") - documents = loader.load_data(query=query) + documents = loader.load_data(query=query, explanation=explanation) docs.extend(documents) return docs diff --git a/backend/app/engine/prompt.py b/backend/app/engine/prompt.py index 101b6bf..29a2283 100644 --- a/backend/app/engine/prompt.py +++ b/backend/app/engine/prompt.py @@ -5,6 +5,8 @@ text_qa_template_str = ( "你是一名博微造价工程数据查询助手,专精于电力工程文件中的信息。" "你的职责是提供有关电力造价、造价编制软件、文件结构及相关数据的精准、客观的回答," "如同直接从文件中提取的内容。\n" + "知识库中已经导入一个工程的全部数据,请你站在当前工程的角度回答用户关于工程文件的问题。\n" + "例如:询问“此工程”指当前导入的工程。询问“此工程名称”指当前导入的工程的工程名称。\n" "## 技能\n" "### 技能 1: 数据查询与提供\n" @@ -39,15 +41,17 @@ refine_template_str = ( "这是原本的问题: {query_str}\n" "我们已经提供了回答: {existing_answer}\n" "现在我们有机会改进这个回答 " - "使用以下更多上下文(仅当需要用时)\n" + "使用以下更多上下文(仅当有助于改进回答时使用)\n" + "如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n" + "如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n" "------------\n" "{context_msg}\n" "------------\n" - "根据新的上下文, 请改进原来的回答。" - "如果新的上下文没有用, 直接返回原本的回答。\n" - "如果是表结构或者是数据库的相关内容,只用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n" + "如果回答中已经包含有正确答案,不要返回多余的解释等信息,只返回正确答案\n" + "如果是表结构或者是数据库的相关内容,仅用于推导问题,不需要告诉用户数据库或表结构等物理信息。\n" "改进的回答: " ) + refine_template = PromptTemplate(refine_template_str) summary_template_str = ( From 0f7c900c1e916bf4c5ef916623ea5cd6decc1fdb Mon Sep 17 00:00:00 2001 From: chentianrui Date: Wed, 28 Aug 2024 09:42:12 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=86=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/engine/prompt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/app/engine/prompt.py b/backend/app/engine/prompt.py index 29a2283..5871562 100644 --- a/backend/app/engine/prompt.py +++ b/backend/app/engine/prompt.py @@ -42,8 +42,10 @@ refine_template_str = ( "我们已经提供了回答: {existing_answer}\n" "现在我们有机会改进这个回答 " "使用以下更多上下文(仅当有助于改进回答时使用)\n" + "你需要仔细的判断新的上下文的信息与原本问题必须一个字都不差,如果有一点差别,那就不能改变我现有的回答。\n" + "在判断回答是否正确的时候,你应该仔细对比新的上下文中包含的信息是否与原本的问题一字不差,如果一字不差,才能当作新的正确回答。\n" "如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n" - "如果新的上下文对回答没有影响,或者原来的回答已经正确,不要在上次回答的后边再加上多余的补充信息,直接返回原本的回答。\n" + "判断一下如果原回答正确,且在新的上下文仍然包含正确的回答,请将新的回答与原回答一起返回。\n" "------------\n" "{context_msg}\n" "------------\n" From 8a5facb5b693a3cf308a508a2396ed841da2200a Mon Sep 17 00:00:00 2001 From: chentianrui Date: Wed, 28 Aug 2024 09:45:01 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E6=98=AF=E5=90=A6=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/engine/loaders/__init__.py | 51 ++++++++-------- backend/app/engine/loaders/db.py | 81 +++++++++++++++++++------- backend/config/loaders.yaml | 18 ++---- 3 files changed, 91 insertions(+), 59 deletions(-) diff --git a/backend/app/engine/loaders/__init__.py b/backend/app/engine/loaders/__init__.py index 241f68a..4f585b4 100644 --- a/backend/app/engine/loaders/__init__.py +++ b/backend/app/engine/loaders/__init__.py @@ -1,40 +1,41 @@ import logging -# import yaml +import yaml +from app.engine.loaders.db import DBLoaderConfig, get_db_documents from app.engine.loaders.file import FileLoaderConfig, get_file_documents from app.engine.loaders.web import WebLoaderConfig, get_web_documents logger = logging.getLogger(__name__) -# 注释掉 load_configs 函数 -# def load_configs(): -# with open("config/loaders.yaml") as f: -# configs = yaml.safe_load(f) -# return configs + +def load_configs(): + with open("config/loaders.yaml") as f: + configs = yaml.safe_load(f) + return configs def get_documents(): documents = [] - # 注释掉对 load_configs 的调用 - # config = load_configs() - # if config is None or len(config.items()) == 0: - # return documents + config = load_configs() - # 使用一个空的 config 替代原有的配置加载逻辑 - config = {} + if config is None or len(config.items()) == 0: + return documents for loader_type, loader_config in config.items(): - logger.info( - f"Loading documents from loader: {loader_type}, config: {loader_config}" - ) + if loader_config.get('enable', True): # 检查 enable 字段 + logger.info( + f"Loading documents from loader: {loader_type}, config: {loader_config}" + ) - loader_config = loader_config or [] - match loader_type: - case "file": - document = get_file_documents(FileLoaderConfig(**loader_config)) - case "web": - document = get_web_documents(WebLoaderConfig(**loader_config)) - case _: - raise ValueError(f"Invalid loader type: {loader_type}") - documents.extend(document) + loader_config = loader_config or [] + match loader_type: + case "file": + document = get_file_documents(FileLoaderConfig(**loader_config)) + case "web": + document = get_web_documents(WebLoaderConfig(**loader_config)) + case "db": + document = get_db_documents(configs=[DBLoaderConfig(**cfg) for cfg in loader_config]) + case _: + raise ValueError(f"Invalid loader type: {loader_type}") + documents.extend(document) - return documents + return documents \ No newline at end of file diff --git a/backend/app/engine/loaders/db.py b/backend/app/engine/loaders/db.py index 0289fb5..00c0381 100644 --- a/backend/app/engine/loaders/db.py +++ b/backend/app/engine/loaders/db.py @@ -1,12 +1,15 @@ import logging from typing import Any, List, Optional -from llama_index.core import Document +from llama_index.core import SQLDatabase, Document +from llama_index.readers.database import DatabaseReader from pydantic import BaseModel +from sqlalchemy import create_engine, text +from sqlalchemy.engine import Engine logger = logging.getLogger(__name__) -class CustomDatabaseReader: +class CustomDatabaseReader(DatabaseReader): """Simple Database reader. Concatenates each row into Document used by LlamaIndex. @@ -39,8 +42,8 @@ class CustomDatabaseReader: def __init__( self, - sql_database: Optional[Any] = None, - engine: Optional[Any] = None, + sql_database: Optional[SQLDatabase] = None, + engine: Optional[Engine] = None, uri: Optional[str] = None, scheme: Optional[str] = None, host: Optional[str] = None, @@ -52,24 +55,51 @@ class CustomDatabaseReader: **kwargs: Any, ) -> None: """Initialize with parameters.""" - # Setting the database-related properties to None - self.sql_database = None - self.uri = None + if sql_database: + self.sql_database = sql_database + elif engine: + self.sql_database = SQLDatabase(engine, *args, **kwargs) + elif uri: + self.uri = uri + self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs) + elif scheme and host and port and user and password and dbname: + uri = f"{scheme}://{user}:{password}@{host}:{port}/{dbname}" + self.uri = uri + self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs) + else: + raise ValueError( + "You must provide either a SQLDatabase, " + "a SQL Alchemy Engine, a valid connection URI, or a valid " + "set of credentials." + ) - def load_data(self, query: str, explanation: str) -> List[Document]: - """Simulate loading data without a database connection. + def load_data(self, query: str) -> List[Document]: + """Query and load data from the Database, returning a list of Documents. Args: - query (str): Query parameter (not used). - explanation (str): Explanation to be included in the document. + query (str): Query parameter to filter tables and rows. Returns: List[Document]: A list of Document objects. """ - dco_str = explanation + "\n" - # Simulate data without querying a real database - dco_str += "Simulated column1, Simulated column2\n" - dco_str += "Simulated data1, Simulated data2\n" + dco_str = "" + + with self.sql_database.engine.connect() as connection: + if query is None: + raise ValueError("A query parameter is necessary to filter the data") + else: + result = connection.execute(text(query)) + + dco_str += ", ".join( + [f"{entry}" for entry in result.keys()] + ) + "\n" + + for item in result.fetchall(): + # Fetch each item + record_str = ", ".join( + [f"{entry}" for col, entry in zip(result.keys(), item)] + ) + dco_str += record_str + "\n" doc = Document(text=dco_str) doc.metadata["name"] = query @@ -81,10 +111,10 @@ class DBLoaderConfig(BaseModel): uri: str queries: List[dict] -def get_db_documents(configs: list[DBLoaderConfig]): +def get_db_documents(configs: List[DBLoaderConfig]) -> List[Document]: docs = [] - if len(configs) == 0 or configs[0].uri == "": + if not configs or not configs[0].uri: logger.warning( f"Failed to load database, error message: uri is empty. Return as empty document list." ) @@ -95,13 +125,20 @@ def get_db_documents(configs: list[DBLoaderConfig]): } for entry in configs: - # Skipping the database connection part - loader = CustomDatabaseReader() + engine = create_engine(entry.uri) + sql_database = SQLDatabase(engine) + + loader = CustomDatabaseReader(sql_database) for query_dict in entry.queries: query = query_dict.get("sql", "") explanation = query_dict.get("explanation", "") logger.info(f"Loading data from database with query: {query}") - documents = loader.load_data(query=query, explanation=explanation) + documents = loader.load_data(query=query) - docs.extend(documents) - return docs + # 添加解释到元数据中 + for doc in documents: + doc.metadata["explanation"] = explanation + doc.metadata.update(metadata) # 更新或添加额外的元数据 + docs.append(doc) + + return docs \ No newline at end of file diff --git a/backend/config/loaders.yaml b/backend/config/loaders.yaml index c69c13e..9844715 100644 --- a/backend/config/loaders.yaml +++ b/backend/config/loaders.yaml @@ -1,4 +1,5 @@ file: + enable: true # 添加 enable 字段 # use_llama_parse: Use LlamaParse if `true`. Needs a `LLAMA_CLOUD_API_KEY` from https://cloud.llamaindex.ai set as environment variable use_llama_parse: false @@ -7,27 +8,20 @@ db: # uri: The URI for the database. E.g.: mysql+pymysql://user:password@localhost:3306/db or postgresql+psycopg2://user:password@localhost:5432/db # query: The query to fetch data from the database. E.g.: SELECT * FROM table - uri: mysql+pymysql://zjinfo1:Dy2Bcr53Hm5xRkba@110.42.234.166:3306/zjinfo1 - #- uri: mysql+pymysql://zjinfo:Y6EAjEEdSYmskA8B@110.42.234.166:3306/zjinfo -# - uri: mysql+pymysql://zjinfo2:GSKcziSdBixDXwcd@110.42.234.166:3306/zjinfo2 + enable: true # 添加 enable 字段 queries: - - sql: select * from ProjectProperties limit 30; + - sql: select * from ProjectProperties; explanation: "工程属性表数据,层级关系包含在博微电力造价工程文件格式_ProjectProperties.json文件中。" - - sql: select Id, ParentId, Level, Name, Code, Amount, Amount_Total from TotalCalculateTable; explanation: "总算表数据,层级关系包含在博微电力造价工程文件格式_TotalCalculateTable.json文件中。" - - - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '线路' limit 50; + - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '线路'; explanation: "专业类型为线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" - - - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '余物清理' limit 50; + - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '余物清理'; explanation: "专业类型为余物清理的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" - - - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where Level = 3 and ProfessionalType = '拆除线路' limit 50; + - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '拆除线路'; explanation: "专业类型为拆除线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" - - sql: select Id, ParentId, Level, Name, Code, Rate, Amount from OtherFee; explanation: "其他费用表数据,层级关系包含在博微电力造价工程文件格式_OtherFee.json文件中" - #web: # driver_arguments: # # The arguments to pass to the webdriver. E.g.: add --headless to run in headless mode From d1242d2080410b27e9f96c732e7d8455c056f696 Mon Sep 17 00:00:00 2001 From: chentianrui Date: Wed, 28 Aug 2024 14:46:13 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E4=BB=8E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E4=B8=AD=E6=9F=A5=E6=89=BE=E5=8F=96?= =?UTF-8?q?=E8=B4=B9=E8=A1=A8=E5=92=8C=E5=B7=A5=E7=A8=8B=E9=87=8F=E8=A1=A8?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=8A=A0=E4=BA=86=E4=B8=80=E4=B8=AA=E6=A0=91?= =?UTF-8?q?=E7=8A=B6=E6=90=9C=E7=B4=A2=E6=80=BB=E7=BB=93=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=E6=93=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/engine/__init__.py | 8 ++++++- backend/app/engine/engine.py | 3 ++- backend/config/loaders.yaml | 21 ++++++++++++++++++ .../data/博微电力造价工程业务数据说明.docx | Bin 14451 -> 13692 bytes 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/backend/app/engine/__init__.py b/backend/app/engine/__init__.py index 6e2a97a..4ee1c9c 100644 --- a/backend/app/engine/__init__.py +++ b/backend/app/engine/__init__.py @@ -31,13 +31,19 @@ def get_chat_engine(filters=None, params=None): summary_query_tool = QueryEngineTool.from_defaults( query_engine=summary_query_engine, name="summary_query_tool", description="适用于任何需要进行全面总结、概括的要求。", ) - query_engine = create_query_engine(index,top_k,use_reranker,filters) + query_engine = create_query_engine(index,top_k,use_reranker,filters,response_mode = "COMPACT") query_engine_tool = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool", description="由博微公司编制的关于电力造价知识、电力造价编制软件知识和造价工程文件结构的知识库。适用于查询电力领域、电力造价领域、博微、博微电力、博微造价等业务等内容。如果本知识库没有直接答案但有解决思路的可以返回解决办法后建议使用“zjdata_query_tool”工具。", ) + + query_engine = create_query_engine(index,top_k,use_reranker,filters,response_mode = "TREE_SUMMARIZE") + query_engine_tool_1 = QueryEngineTool.from_defaults(query_engine=query_engine, name="zj_query_tool_1", + description="由博微公司编制的关于电力造价知识、电力造价编制软件知识和造价工程文件结构的知识库。适用于查询电力领域、电力造价领域、博微、博微电力、博微造价等业务等内容。如果本知识库没有直接答案但有解决思路的可以返回解决办法后,且在询问工程中单位的具体数值,例如用量,费率,合计,金额等的时候建议使用“zj_query_tool_1”工具。", + ) tools.append(summary_query_tool) tools.append(query_engine_tool) + tools.append(query_engine_tool_1) # Add additional tools tools += ToolFactory.from_env() diff --git a/backend/app/engine/engine.py b/backend/app/engine/engine.py index 379275e..4bbd993 100644 --- a/backend/app/engine/engine.py +++ b/backend/app/engine/engine.py @@ -86,7 +86,7 @@ def create_summary_query_engine(index, top_k=3, use_reranker=False, filters=None return summary_query_engine # Create a query engine -def create_query_engine(index, top_k=3, use_reranker=False, filters=None): +def create_query_engine(index, top_k=3, use_reranker=False, filters=None, response_mode=None): # 创建向量检索查询工具 postprocess = None if use_reranker: @@ -103,6 +103,7 @@ def create_query_engine(index, top_k=3, use_reranker=False, filters=None): node_postprocessors=postprocess, use_async=True, streaming=True, + ResponseMode = response_mode ) return query_engine \ No newline at end of file diff --git a/backend/config/loaders.yaml b/backend/config/loaders.yaml index 9844715..723cc3a 100644 --- a/backend/config/loaders.yaml +++ b/backend/config/loaders.yaml @@ -12,16 +12,37 @@ db: queries: - sql: select * from ProjectProperties; explanation: "工程属性表数据,层级关系包含在博微电力造价工程文件格式_ProjectProperties.json文件中。" + - sql: select Id, ParentId, Level, Name, Code, Amount, Amount_Total from TotalCalculateTable; explanation: "总算表数据,层级关系包含在博微电力造价工程文件格式_TotalCalculateTable.json文件中。" + - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '线路'; explanation: "专业类型为线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '余物清理'; explanation: "专业类型为余物清理的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" - sql: select Id, ParentId, Level, SerialNumber, Name, Quantity, Rate, Sum_Price from ProjectDivision where ProfessionalType = '拆除线路'; explanation: "专业类型为拆除线路的项目划分表数据,层级关系包含在博微电力造价工程文件格式_ProjectDivision.json文件中。" + - sql: select Id, ParentId, Level, Name, Code, Rate, Amount from OtherFee; explanation: "其他费用表数据,层级关系包含在博微电力造价工程文件格式_OtherFee.json文件中" + + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(调试工程)aa' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '大型土石方取费表' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(余物清理)' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(余物清理)(1)' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from FeeCollectionTable where FeeCollection_Table_Name = '线路取费表(拆除)' + explanation: "取费表名称为线路取费表的取费表数据,层级关系包含在博微电力造价工程文件格式_FeeCollectionTable.json文件中" + + - sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '线路' + explanation: "专业类型为线路的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中" + - sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '余物清理' + explanation: "专业类型为线路的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中" #web: # driver_arguments: # # The arguments to pass to the webdriver. E.g.: add --headless to run in headless mode diff --git a/backend/data/博微电力造价工程业务数据说明.docx b/backend/data/博微电力造价工程业务数据说明.docx index 425772fc2d814390b163a4c7eca93c73622daf2a..670ce04d062e8f88944bd8e0d4d4be00875cd8ba 100644 GIT binary patch delta 10848 zcmaL7WmF!`(l&bI?(S|ugF}Ge?gV#tCpb)S*Bf_t4elYhLxA8e!8N!Yo^OBe+3()# ztkY}t{HU&;s=j)9rl#t;c6zpn=R&xuhe)%60D-&`gzy2?F~vSM^iHZvG?lZ6?8ZYV z`xx0gI_Tt#UsT_->`fCEQ|y(W?s%C$Y>nDm(vm89$yzw?3TSdUHvN?F6~)_VSRvBVwV(EmU_rzkW!@h2ag_?kLUCU$7SRw{vR!c| z%M(QJ+K>YR;&go7%LGOkve5;+zi|DIXd@iN8|q+vGo00l63X?dRHTKrP&T&IIZNpJ z>%83fyBo^I+;{@*U=e=U{9AT&lj$`dj0-`&UF+V@FopW)$w6UQXaPB#*swTOvATw5 zqc-cwU64qzpd;fFMP}$zEr>g?MJsgNZb~;y*gpbTf9bPVC?4G&<$%{Q-wAq?UtgZ|8hqvqOw_R$(6LYN2fcmeMh}crlFnOMgHciaa zrcKBk*jhtLMhcaA!f+I1B%8YyOE;}`+pu|;=L)Lf7(5Xb^@7yheZY1}S*`4X3$YUL z*?~bHXE8~{|o4SAimnB(?q zhc&n@KXt9-&{k&BQiJJ_?l zTE7-|DMV>3g1yW6!yl)Pmxc1PC4|9FmTDyKJO^zLLhp4GOV79vD4r0U3XKOKoX53! zB7#6BmLL$?J9-|DE@rH*ZeDiguKzr;P5Nu9JG{8v8x?+VnlX2Z>3X6z>Adpw{4K0ZtrCN{Ar+;y9y)A zDV+A%wx%@`AUHigixD7w0@%?n`^?+`kGAWV;V~CnIHshJxzPrm+>cv3hHqEKUKx9= z6jK7A@P^sp+-O{{oUGWP^qx(OF?aKyruWV)v*CMAX+qIdDMGj-v8;u`dnUA^2|dwh zx3{rUu#$?B5`?*g;n~vn<>T*fvX-pT2fh2%=khb@mM!M<&Uk+e;F5PCdM7DN8J55j zDZva!Cs-or1IveaI$fHag1UBxHk2jR5|KpNTuXv`YQ(XhQu6&=cMJ54<@cf39{Q^hy98Zzxh2GDFa_#$F0%q{7FAAMt!ABiW|rjJ-26 z#9WKs^hSB7I`WfG%|SA@=J=0|BeeT?-n3iKwKEJQ3a&!CN)#Xxg?+d`qk>ZLu6 zxSjX8-xvr73SZIBAH|68!gvqSF8zS;yK3|LC62*Eki$Viwq>*9d;&BmE$QiJiL}cl;0)v(7 zpbwR~gF9<47Q?T%$fR5uuC?}8#~wH!1fl>4J&(e0_%GK{rJU~hKbXnhN@f;yPMRd$ zd@5%x+b7l#r{#XT&Z}MRu4YDsQHD(V>LPXGLB-{I!gq-^$D$^;9 z{t*bdL>Cf}qH=}T7R7L7Who$#sG>UwK+PHo_{}W3^97spmzE_V<5kF!EmEXi6n-=i zk3yE+W|pJS@6FJkJPc1NfjIy4C77ZVvWH@nO5Y{0xpI)ks?%n*a4Sf02b0r~%YlFZ zTR)gqAh}85usqsfv)s;*7B&48MIiZK-M8a(fiTKXQtw=x6tmHEQmouS9=R4)?Gl~C zYNIKYz%cJZ1 z#RpGz{W65IqAB>12|`l9w_ z$^;%57M~YO=g-J;-Of&mB{=Zd1k1o+j)0BS(E=r}5VM47G&YOl80>n0UJ;cz^mP<0 z!SU`+YJm{v$f2#-JJry9y{jLJAB#r!%1^A2P=>GgWO13WmM&mB*f`8OZBvlr{E2>^ zpcT+Rc0#GiiB7Fso!oSCLfrsQ$y41#>)eKCHMN}__+t@)eg5!Wc zw};DJ-i|14-#r)1>7qPh6mic9vzgYp__aH2{}CRTUHW@&T|N*mKLt-+!oq2v@bC_^ z3wNPxsQ{3be!o&lU)o|>w93(Q#a@5V8^EPpw3KI6ChM`EX+5)l8!p#mE)wj-%wr>u|Znmdl(YbDC?xnRq)mKAweVgAT73xy7Ytu!$ z_?sApr3<@&Em&bBw@ug+CcQZRCM&eH21Y|to>n!!mXIl$t)h#XAfbsu{hhQld-E%9?MiY=+@)5FKdHE z&&SFXm=hN}h;Q&TC4%7Qv5(|Q8Q9NLxE%bx*f~qHuEi4VY1)=GKqR-zw5~;Ic{zy5 z7sZn@tlgO)?ywz0Q(rDx?P|Lnv-jOvYyz0ac4SIWAhjtd@uZ4qCTlIr@fjxlokE50 zr)`J2jO}QrZ?}Gk>Bxj9*;%hQ`99qR_kF^<>4^VpL7I~1axl@TpJ>c{HdIF~^Ihfp zh?v40wj*^yhbPs>82|sDf588TgT3KADPtulO(op#YcKp@yjlw@54b!4=si?i9aJC(j zrG7xau7#Tk1ic#>Gr3kweaDRL9hCoG-ar0HVzx!_q(D=>Lz~Gxm+_9u|3GF-x!Bs> z2G_M*rVm^~>{IR4*|@UHR-m}eVbd%o7@W2^Hm5D%`OjxgS3b=l%C_!D^jbn?5cOno zU3y!e*zDW`N26UXze!HOwQMPr@p4>HyvbY3I6V*Z5$VCTY#`#KwN+T3x5|!Lo0hlv z$rs@D587gW{mAhx7QP{Qxh8NdfmddHfzWS;@ zQ5kfi>-SThYN|WCk`*lpPkoIT_GvEDRbag>_roioZr#J|KIu4DPN1wH$+VW9lb&(( zK{TdmX2VJCG!3e&2ble6(a~cAJ00Dt3GH8XY_eZFP?xKsF6%lv5D}L}#{(>D{(D7ZLW~M-2FI@AxX&^edGyHJO6Dnslm1=h!s0J-cG%7*7?A`hjKk{P{T5nKF zACRP344I=~gWPsC9;%~CknDAJtM~5@O&qqG&f-UJC=bpONgSY4mjpznxLB~vs|B(T zbEkf?hiv7#l7=qG)48!=ZHBRySsA7VVhcz&V1C+l#VNixe$DYmuX#abhsY&4?EXBD z74-??2iwHYq_B#3#whhSbFw$I|NP%NVZNgsgaLulQ2+Ve0w?fb0mYiSYAd|h{u}8p zX!7e6-76!Ur;E<=`NF!8=A)S=jN;-c0*Ug3{x75tiA6-rE7o2je5vPpU)`S1`r;CE zI*lk0EWrVO7AT5rV_qVQvt~{}YPMt$RyjH&`W~_ptS%EA+4|edLdS%bNwKhe4hR~& z!=8(*A*;T#rM%Aw=uvtNGLC<1+bs}B^p7kxj_7Z%QFJxXkWPTf7q<_KHHQg84ON0| zGTK4iZlrG8Ok_>gAh_O3+--eYunjk?U$H3>sFfT4V(LuK21CXRW>g&^t$x<$gm<0~ z>g>enmy_{ni?Q#bSqkacDp<6Bj`Y#V#}pV+6%CMG4%MXue!8FA*{i5;{Yg+kWkPsqVz|6t$mD9y9DCt1$XAeQc0pE-*FaiS;i@9 zK$9k6R?@@$c7$^PF7~pksZY?|bY^WI+m8WXMjRH7$t1gQ zBzVjk;Zes{AY(!FA_Ir)BP5|wCpmo6EH{EhRwY$$fo&rzWLld8yYNqB2hrHCP-o~! zo#I^T9#$VUJC7#3x;jFHiRic5$Om|sutzYmHR<70S#6#~h_pq_BxY`@@OE)1#W>fF zCpSYKJqSOK+||8NP28tu>{U3hjMFhK<|8p1b&Epo0r63jeGHxyyr&aKjI4Q7XiofH z7Ptr7((ovjdaH&_<|5ej#8bW410xz+Nejy6e%|CEI$WY5EXz2Oth^!*I;zx~^`z=3 z4J96s3AEp`$0BJRmcVx~_?Y(s#>f|4Kv`WTMS%?uY zBk*JLAY@cBhZKC|qO0Y#7@#pr_>tzozlSCOc#c7gyIBkMUAweYJB4C=!5}T!K)Yi$ zRhTkM`mz8m8DxcYS2`G)>71#%cE`rtO+j%t)R&k-Ollb7UfjDP_v)#*fH#$;_j&f} zdX4JEz~G7JaPM*dYuAgv$CIz?-5MZ}yTnu5urL%hG{5tp`Tdzc{eZ3aDnQWlK5DQI z5L*37fBfmk(d+WK)mbbSZ$P%9C2cIxd%!`+n@{p7f8*=ClGWDmS4>up1Nqa0Y`*RY zFrQ+Yd(b)hguCcUj4xEisd)L0B1-p?2)>pzKG{nBPCA*6vCSs6GiLN^c>wq^<#ZVq zEo)dIi=Ok~o2~X{F>QAGsg8CM@rrX7K;K-LE;58tnve<;`q)~?^u06|f%%q_2j$fC zQ_gAZvy+AJHKgM%OhmqrK~igMZiXA?7~1#Ycw5IKvokk~;U=D-3ehf&e%HA%o3U+Uy?JY{WEmtpr!NgOkH#F@&|o#8!WdV3SO{e)?m) z$V~kOfA>QxDbs@wRIIs4L=r0^X6@&vsQSaoR>gfE&rypfc>TB0d>B(Dqc?V%BV+e{ zVq1~t(vM%Z)H%1U*}-h8#vbjffbpRqT9oVJTE*{W*qmc`jk|rjspAXyps?aa>=t zgKJgPo5p6hM{Xey}c(X8qTqGU;#}$W+)US5QvlSU#YeKlcjjiuYI*Q zcX0bBPjRZNt41V+>%UR)g7%?n*Bl~dx{I<@SXx_?rlUN5?va@*1r}d7BRzva`2rl> zhRDV{m^!eCzk;8IKf+?lM2-ALqcIhobA@;N_pj9)yxkzWW%Y-yZzWHE562GAfz|e> zv0DGhB7Lf?s*3{juN>K=Em2sBCXslsg=b`dv|I2hi-dUyb|x+i%Ms}w_MPUR*Vh)- zhJ>Uv;z_5#BS_pp%n{jn<`>Zm!;H&~+;G+hz~Y*eN$(8#my3LqKtr8h!mEz4Z!|Tm7X>Dwf|buo&-|0gcx4<&dapa zmvGs9V%I=Q`8~#LmP!nZhgZ-A8w}_XZl`fbY z*&Za=RWGC@;E*W2F+wZR!=JIQw=@i&8Qb1<#?ru-yL~J{s_Mp|%_<$JxND~R0gKi} z6#EMde5j{LOgo>3iVt=U4X3pRepSm}a4gx=+J!n@M0+jr*Z$WKfT80%2AJfzWzYik zLd`89rtHu3Gy5{@fn2T1s{!*}osL(~dew1e!}4jljk%OhYuGJrbj(mwxd3Up?4adq za%_!V3(pqHji=b(QN%ui@BF^r)cS@XTdw>w-wK04tp-O{N7=}aV*n-eTmnW^d}KB?AsH`&3I_6Ep46dBi5-6-95Vaklqxfj-B^{Euw`xcdIWRZI#N> zn_}d%^hMCnA;8H*{!cDHFTG5!P=j^RsOx!Ef@OmdgEr`S;7vO4H^}@~eyl8UxiJmH z1f2p;;c)@I#nOx-TT^Ol(XutSS1OS!`C(p9ZAU4Ouk@53yG#qD)8FFM`KzyfU)Sgr z3$7G6`2r9-nrt1Lo{n|AFe)mF^_u=NGFyp4Va{2&%#ZR*E9iPTL=hdt9R7J6ui@q? zURw@r=5{qb0|?t&P*5t1AC_e&J-z37(|!%svv5Tw(+VxmessGaEVAJUTXWg^3DdxL z1_>KMTQW0ByY8}oCdx`?)rPVtH2*8b-%+=tyQaFvmgC9l6-S4je}z0ix%1PwXIJ9~ zE31v>cA*Xo9%iOulwtQr{I4h&Us_prA8dtJMUR$6dx2f?)8!I_wsJvyDOW73OCFGQ z6Q^$2DLV@8^rDqXsZN`{-T9GR=7qNI%KSOb^j}sh@9&4#bfRB;I34WdcT!5QZPkzt zQu&xQXOKLixs0~N(Vl!?(RU6HZTpaYqI1U+1d%xwahI#{mVJBah2|N-lFqsvK5OY= z*ayc5Y(VeD$Q8TbZ@d0Bykj)z&j$lKH3zmT){p}-pw z4o;vl+fCsXAo#2)xqOS;=&P+SQHvER?6OnbQNdY z=o_2~HmZ#WNV1i}J>?9ySEf3J&bH0m$r_&Ez7a@yGH$1#Z-J}8fLAUz!`QuTOeXjx zabu*=fyfeBtcC#LYx9t0pe>AK3esCWU#7k17Ow<{=6N(dGw!w!f+qth2t z=zwwi>-E(Aopb6B3tr8+n*q@M%>5nSB-1y#t;@&l05D1Qlty7=sHL#B2i%7cnS1Y@ ze9uh|4F=}=6LGFD9-1*yJtAfDqFT$dkkmW_gV4G7>q)~ugoBE?8HP|(@hG|>o6Fcr z6<9H|bZc~r?XYhtxW(YG(9Hv`AjdT~6amp`7#kSIR$1+hc99I>QY~j}i|8RNHv}hP zrIP4V<`?_k0&Qk7YS`{v?QSHy5zoIqG@O@_$fWUT?J}8usQN~zjOLA3kf(+)1Ch8_ zI@Y3wS=6fs`9~p5reh*v){GMN=A?TI(u{uAO*-qsYG5;D&s`;MavDowCc-D4Cg8Zo zreytcW;bh~GE<-$GG48VI)$b+^tIQv{BySfM z0v@1DBl>l4xR1|r9p6himWFzN4nP)&BIB>Tgn7D!BG@BFX=jHpArQS+sRo;pLVi2Q zV7vOII2A3LXP`vXq?m#aYDVC-0~U5wW^jNk{AR!>Fl>^Su%0Y=(QfB@>gS()-*l)t z@1Gx)m@s&?#qEit6cgh3C>_2vjXabXLmR*er|*8WXU(FmW6G2H?bLmoa0gI~4p{S& z!73#Y^P-W7!$hDy)4Yn^%?S=m{S(3SC3xhQ&hk_N`Z5A&VK# zW!Ja)Q%4eBv~qrZcTZ4aul0u9w;Zf)vU4Jyf}-+C6y`5!2#pYZu+wbg7>L6ZfZWU7 zQog^{?NHw6h$-=ywjl_Vwg=4TJC{{{^h@pNe?WwTv=R;LQ4WmbMe-_;WrMhcJA2dY z)9&z=Wa&Z3UP!oTFR%mI{6aAf&x%j5L! z&q3a{Oi-zO(c-Q*B`_7HoB>@xv9KLXrEXG+kTje2KMZNtRLb#=C_OyKcY;8Pjh#YW zg{eFTIzl0l9c7)+V&AAB+d~`kWqUe zx0%jB%O)4tFF+kD`f+TSlAF$F-Gr7v37f?Gd?sP={li?n3*flSCjJ+@n!_3{UHQkc zQe)lJ0_CsfQ#-Jm^+(lTg&2z9MeThouM|oM283J+J+gn_mv<#6!j zF~6rVL=P0jx6p@pQNrhxYN zr^9y(kbN!PI)oD#4GN>Y*!g6j@bjXB0Q?m*C+07fc+QHOi!M7}u}ryjDd5BrxKjT7*E@KKGT)cT3m{9? zp-Z?EZS?TDz8U*kze%8r1rsYcz3Hto%zNcNI4psF;3);*|MrtKrDfpT=*nv4;4DEMq4Ya zZz8t9S-cO^*eAnGMain>t3u;8Pi-cKYc4up9II@JT|2HTDHP6Y8cf7vnkS9O2Vdjy zU*_9bH)Y-e3 zb&3oJ8Yhi*z+EemmZbcg!yek_2P{v!gvwu}@~4lrk3U2%^Nc}2%dLn(+(6WP3R1`d zLmiIQT*Fke2b3RNZIcQwcMtpTPlVNp!${dk3!DKye2P@(D^3ynvmKvU>w1~wP+nwQ z5{0^@RiAimZK{h?joGWuNrp<>xgDX@;)7eYp8Vv4F z+Oqke>`gs2AxL%ujG@=Ph1;el*~wd{^dt}DtzK!n?#95HW)7oXS069CBUg#kmu0CF z6s80c*$Xm+)dkzJF-h(n`I1AIG(9>&3}IsF!_Ja5(vm2ZNENxS(j0D@6us7Qop5H6 z^)5T7*7eE#d@TIk*-&3uy8p3xhs8?@Z~tbfI^mD2rY_2NfW#x> z@GV_+IR;^SmsMSMzMKQ^vwp$HT&Jhm+k>D(=UU0%(=_e2@pv09!grRZhf?s}w5aP} zh6&q?Jg(j%)^l47zg^y&K~!zIB7x3Nf}j%oJo=2Ga0&cRz2LJ+(=~24H&G?O`oJi8 z=zOz%5cIf4!~f6pVrK>B!}$9FnMDM%eZU9S)J6U|9G!RvWYFta36aDMl1b#wRC%eS z%h-am?B-ZFG66|Dk0^pTFH)b;p^4_Mo&PkCc$`d|}@WqU&#m-XWd)0bwi9Saa0 z(zx|TkQ2nBA!(7gwq3IFrxqSWA|Yp$`3jN~nZ#TzrXQA8cuE`m%gsz7%Th~NBLQTE zjFPjkd`=L>imr3yNA#4m7IhxS4{O_2Q@xat3uC z6={gHM4Dta8X{6O6Tu4>OZLrjE$P1sbt(f1pe%8d&*|t>(d?x=XQVGg84E}E(NVD; zNkW=&lCVzB#6uue{%*t-|8moUa0fUr3magZdaGE=zio2ijYE?yGToO!C$r?2s1it$ z{|VI~_=%x6bPs>$gxmvvW`ez}I1p^pmk}m@(no{SnZa7PeDn2z%Q13<-CvBWh3J|q zG;V8P4%s<$6TG=gsSqC*k6esiZ;KIOq~;GHs5d_&*1v~c6DLRE<={#V=?CDdJLKk< zPQy|H{(e0@PfHNc5aeti;S^0q^h0MNbhl-CGQ&ROep&wN3M)#0zjqIG&(tlU?f4}M^{FrH=sOP`iK|7r4qU^`a)DRUYnK=t?1?6Z| z(~I9@-lKmC&`J>3|4D97p9T={4E8L>plgCe-1Z)jWg+lk(Pe(E@4-?iHe>w!4pDnZ z8D<{j&ZFOc@AG8Z!J-I?T9^)bikvA1H-&A{lkAR=_jn>gc|qtS&wX(%sWx|aqJ#i= zo$cx@2+ju(@+IZR{*X&_{*6iIHu#2}yKhpqJTMcaEdl}sVv$QiE2%_$UYISPvBA(+ zGwsmTLG+RGG>^ldjzr@+HxfS^EV+i;lq{8NjGcPXhurNt#8k;TImC2FtnCO!S!|l1 zIdcU1K&L-?6{p_jXmD$+Cto4nQ!B~LvJl{NYy>bW8#aO*)4lBNI{}0l%*aL!Bu?18 zbI5|vL%M?&eV9MJP- zhdxfwyBj0_c(bhzF3iNnG|0{<1(O2Ck7(Ok0UkI(!!O?C=x1UU5vW1vy%NJ?mM_ei zw2LrqpoOAnm=pd(syK=%+WY}BPLbPt9X4ZMt+QL_>iOTFNUZ*4_(&ocjPt}Q(F7Y*=C#6}#VAok1?=8Od6eEl#qnV@HfO0=x zFU!cop;p7#u4F6fO$N_y3bp4n@0fBYN_wC5dlx9ICHf6bQUk`pf4u^+9H;}%`HEhDb%x}-l~ zo9yp=mN@qzAr5z&>B4MgcZDwkF5`IP4+?x}&`qdeo_)f&+YBijWbe@eXj|~e4hx{x z1;X%Jru!SE*Y&D)Se4}zD1uQu)t0n91uL< zB90GWJTAt6b0fiWTwFx|!_xa7lHR|kcY!mxsEPiYP4@3`cJMNnFhnevh?^Z!p9QSM zO+x(to*5_*i1;7P_x3MeLRr9UY^2~4Zgism&RzansUAGTO-=Og56wT3*uUDpZh{9! z=b<6~&q(cmkDt=M$8FR^|5*t8-wGPw`1kSurg;6M@h=1Q;3*yfNI4uZ3NH_&8xB~K Umkbr-y_kj$4FYL={73Kq0U`Dg?f?J) delta 11510 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 From 327bba75d5bfea4ed7df7165f0a4d47d8f52abf2 Mon Sep 17 00:00:00 2001 From: chentianrui Date: Wed, 28 Aug 2024 17:24:55 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/loaders.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/config/loaders.yaml b/backend/config/loaders.yaml index 723cc3a..af5d2fe 100644 --- a/backend/config/loaders.yaml +++ b/backend/config/loaders.yaml @@ -42,7 +42,7 @@ db: - sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '线路' explanation: "专业类型为线路的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中" - sql: select Name, Code, Calculation_Formula, Rate, from ProjectQuantities where Professional_Type = '余物清理' - explanation: "专业类型为线路的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中" + explanation: "专业类型为余物清理的工程量表数据,层级关系包含在博微电力造价工程文件格式_ProjectQuantities.json文件中" #web: # driver_arguments: # # The arguments to pass to the webdriver. E.g.: add --headless to run in headless mode