From 6a72233a9782e6fda0e6e3949e7f500593805df1 Mon Sep 17 00:00:00 2001 From: ouyangyouzhang Date: Thu, 31 Jul 2025 09:23:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=90=8C=E4=B9=89=E8=AF=8D?= =?UTF-8?q?=E8=AF=8D=E5=85=B8=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?IntentRecognition=E7=B1=BB=E4=BB=A5=E5=8A=A0=E8=BD=BDjieba?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=AF=8D=E5=85=B8=E5=92=8C=E5=90=8C?= =?UTF-8?q?=E4=B9=89=E8=AF=8D=E5=AD=97=E5=85=B8=EF=BC=8C=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E8=AF=8D=E6=8F=90=E5=8F=96=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=EF=BC=8C=E7=AE=80=E5=8C=96=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0PromptTemplates=E4=BB=A5=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E5=90=8C=E4=B9=89=E8=AF=8D=E5=A4=84=E7=90=86=E8=A7=84?= =?UTF-8?q?=E5=88=99=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/nouns/all_synonymous_jieba.txt | 237 ++++++++++++++++++ .../intent_recognition/IntentRecognition.py | 95 +++---- rag2_0/intent_recognition/PromptTemplates.py | 28 +-- 3 files changed, 297 insertions(+), 63 deletions(-) create mode 100644 data/nouns/all_synonymous_jieba.txt diff --git a/data/nouns/all_synonymous_jieba.txt b/data/nouns/all_synonymous_jieba.txt new file mode 100644 index 0000000..ddbc686 --- /dev/null +++ b/data/nouns/all_synonymous_jieba.txt @@ -0,0 +1,237 @@ +主材价格 +设备价格 +单条设置 +储能预规 +砂子 +中砂 +造价2016 +机械进出场费 +√标记 +建安 +Q/GDW11338-2014 +Q/GDW 11338-2023 +未能成功匹配的数据 +2013年版导则 +非标准清单 +连接 +表七 +场地征用费表 +预规2018版 +单个基础用量 +主材的规格型号 +挖方量 +GT7-23 +消材暂估价 +招标代理费计算 +534号文 +标底 +最高投标限价 +招标控制价 +控制价 +2014线路清单专业 +技经指标 +初步设计清单库 +施工图设计清单库 +灌注桩直径 +电力清单2021规范 +电力清单16版 +OPPC +修订批注 +删除修改记录 +修订记录 +取消工程密码 +调整依据 +材料 +机械 +整套系统调试 +消材 +辅材 +计价材料 +电力建设工程常用设备材料价格信息 +承包人报价浮动率 +报价浮动率 +国网电定34号文 +国网14规范 +国网2014规范 +Q∕GDW 11337-2014 +国网23规范 +国网2023规范 +Q/GDW 11337-2023 输变电工程工程量清单计价规范 +表头属性 +DL/T 5745-2021 +DL/T 5745-2016 +合价小数位数 +清单规范使用指南 +主网预算第四册 +2018版定额使用指南 +人材机结算价调整系数设置 +总承包服务费 +装材费 +主材费 +未计价材料费 +查询 +显示零费用项目 +显示零工程量清单 +显示零消耗量 +显示空特征值 +配网预规 +财资【2022】136号文 +【2023】9号文 +20kv及以下配网工程 +配网工程 +空项目划分输出 +可研估算 +初步设计概算 +检修预规 +电力设备检修工程 +设备检修工程 +编码顺序显示 +迁改工程_其他费用导则 +技改工程 +程序启动失败 +清标软件 +青海清标软件2017 +自动更新 +注释名称 +标注名称 +用户定义组合件 +物料清册 +标准物资模板 +定额[2023]26号文 +软件崩溃 +商品混凝土价差调整 +封面 +签字审批 +编制说明 +表二乙 +表三甲 +表三乙 +配电网工程预算编制与计算规定 +供货单位 +文件夹路径 +预规2022版 +一批工程录入 +2022年版配网定额 +表五 +表三取费明细 +重置模板 +恢复默认取费表 +恢复初始 +输出文件格式 +批量设置行高 +南网规约接口 +价款调整 +软件操作手册 +表三工程量合并排序 +增加索道级数 +Excel价格库 +Excel库 +市场价系数调整 +红色三角号标记 +编码重复 +首页 +主页 +西藏预规2023版 +选择报表 +降低层级按钮 +商品砼 +商混 +小数位数设置 +数量精度设置 +工程量精度设置窗口 +工程量小数位数设置 +取消密码 +查看取费过程 +表二甲 +表四 +其他费用明细 +总费用表 +表一 +人工材料机械 +人工/材料/机械 +工程量转换系数 +贷款利率 +年度贷款比例 +金额显示单位 +报表单位 +上级消耗量 +补充人材机资源 +加密锁 +狗 +回存资源按钮 +保存资源 +调整计算式 +计算式编辑器 +加减乘除 +费用项四则运算 +新增子级 +添加子项费用 +162号文 +编制期价差 +价差 +人材机价差 +云账户 +报表编辑 +计价依据 +造价文件编制基准规范 +一笔性清单费用 +一次性费用 +独立费用 +包干费用 +工程量录入界面 +建筑工程界面 +安装工程界面 +添加定额 +添加主材 +添加设备 +含税价格 +含税 +不含税价格 +除税价 +设置颜色标记 +增值税率 +导出版 +补充主材 +计算基数 +费用基数 +物料单重 +批量查询物料信息价 +1980号文 +人工展放 +人工展放引绳 +技术经济参数 +地方信息价 +通用设计 +复用清单 +刷新组价 +TBS +挖孔桩基础 +掏挖基础 +组件参数库 +自定义组件库 +构件库 +工程税金 +运输距离 +工地运输距离 +输电线路工程 +反查资源 +红色三角形标志 +红色三角号标记 +充盈量 +工程项目限价 +清单控制价 +投标限价 +装材 +主材 +未计价材料 +招标人采购 +甲方供应 +业主供应 +乙方供应 +投标人采购 +刷新清单顺序码 +技改预规 +取费模板 +其他费用模版 +工程费用模版 +Excel物料表 \ No newline at end of file diff --git a/rag2_0/intent_recognition/IntentRecognition.py b/rag2_0/intent_recognition/IntentRecognition.py index aceb439..c79099c 100755 --- a/rag2_0/intent_recognition/IntentRecognition.py +++ b/rag2_0/intent_recognition/IntentRecognition.py @@ -80,8 +80,49 @@ class AsyncIntentRecognizer: # 加载软件词条名称库 self._soft_wiki_library = self._load_soft_wiki_library() # 异步检索器将在create方法中初始化 - self._noun_retriever = None - + # self._noun_retriever = None + # 初始化jieba自定义词典 + self._init_jieba_dict() + self._synonymous_dict=self._init_synonymous_dict() + + def _init_jieba_dict(self): + """初始化jieba自定义词典""" + try: + current_dir = os.path.dirname(os.path.abspath(__file__)) + dict_path = os.path.join(current_dir, "..", "..", "data", "nouns", "all_synonymous_jieba.txt") + + # 检查字典文件是否存在 + if os.path.exists(dict_path): + jieba.load_userdict(dict_path) + logging.info("成功加载jieba自定义词典") + else: + logging.warning(f"自定义词典文件不存在: {dict_path}") + except Exception as e: + logging.error(f"加载jieba自定义词典失败: {e}") + + def _init_synonymous_dict(self): + """加载同义词,key是同义词 val:是对应名词""" + try: + current_dir = os.path.dirname(os.path.abspath(__file__)) + dict_path = os.path.join(current_dir, "..", "..", "data", "nouns", "merged_nouns.json") + + # 检查字典文件是否存在 + synonymous_dict={} + if os.path.exists(dict_path): + with open(dict_path, "r", encoding="utf-8") as f: + data = json.load(f) + for cur_data in data: + synonymous=cur_data["synonymous"] + name=cur_data["name"] + for cur_synonymous in synonymous: + synonymous_dict[cur_synonymous]=name + else: + logging.warning(f"名词库文件不存在: {dict_path}") + return synonymous_dict + except Exception as e: + logging.error(f"加载名词库文件失败: {e}") + return {} + def _load_soft_wiki_library(self): """ 加载软件wiki库 @@ -105,7 +146,7 @@ class AsyncIntentRecognizer: """ instance = cls() # 异步初始化名词检索器 - instance._noun_retriever = await AsyncProfessionalNounRetriever.create() + # instance._noun_retriever = await AsyncProfessionalNounRetriever.create() return instance def _load_suffix_keywords(self, filepath: str = None) -> List[str]: @@ -277,7 +318,7 @@ class AsyncIntentRecognizer: """ start_time = time.time() query_keys=[] - # 步骤1: 使用LLM提取查询中的关键词 + # 步骤1: 提取查询中的关键词 try: llm_start_time = time.time() extracted_terms = await self._extract_keywords_async(query, use_jieba) @@ -289,44 +330,14 @@ class AsyncIntentRecognizer: raise RuntimeError(f"异步LLM关键词提取失败: {e}") from e matched_terms = [] # 存储匹配到的Term对象 - # 步骤2: 使用向量检索找到相似的专业名词 - try: - vector_start_time = time.time() - - # 创建并行任务列表 - async def process_single_keyword(current_key: str) -> List[Term]: - """处理单个关键词的向量检索和重排序""" - vector_results = await self._noun_retriever.query_async(current_key, top_k=5, use_intersection=False) - current_key_terms = set() - # 添加向量检索结果 - for result in vector_results: - if isinstance(result.get('synonymous', []), str): - result['synonymous'] = result['synonymous'].split(';') - term = Term( - name=result.get('name'), - synonymous=result.get('synonymous', []), - description=result.get('description', '') - ) - current_key_terms.add(term) - if len(current_key_terms) > 0: - reranked_terms = await self._rerank_matched_terms_async(current_key, current_key_terms) - return reranked_terms - return [] - - # 并行处理所有关键词 - keyword_tasks = [process_single_keyword(current_key) for current_key in query_keys] - keyword_results = await asyncio.gather(*keyword_tasks) - - # 合并所有结果 - for result in keyword_results: - if len(result) > 0: - matched_terms.extend(result) - - vector_end_time = time.time() - vector_time = vector_end_time - vector_start_time - except Exception as e: - raise RuntimeError(f"异步向量检索关键词时出错: {e}") from e + # 查找同义词 + for cur_key in query_keys: + if cur_key not in self._synonymous_dict: + continue + name = self._synonymous_dict[cur_key] + matched_terms.append(Term(name=name,synonymous=[cur_key],description="")) + # 提取所有Term对象的名称并排序 # 将set类型的matched_terms转换为TermList类型 term_list = TermList(terms=list(matched_terms)) @@ -334,7 +345,7 @@ class AsyncIntentRecognizer: total_time = end_time - start_time # 输出整合的时间日志 - logging.info(f"异步关键词匹配耗时统计 - 总耗时: {total_time:.2f}秒, 问题关键词提取: {llm_time:.2f}秒, 向量检索+重排序: {vector_time:.2f}秒") + logging.info(f"异步关键词匹配耗时统计 - 总耗时: {total_time:.2f}秒") return term_list, query_keys diff --git a/rag2_0/intent_recognition/PromptTemplates.py b/rag2_0/intent_recognition/PromptTemplates.py index ed458b8..4efdd22 100755 --- a/rag2_0/intent_recognition/PromptTemplates.py +++ b/rag2_0/intent_recognition/PromptTemplates.py @@ -172,29 +172,22 @@ query_rewrite_prompt = """ query_rewrite_prompt_pro=""" -# 电力造价问答优化工程师(精简版) +# 问答优化工程师 **角色**:基于历史对话和术语库重构问题,提升知识库检索准确率。 **最高准则**: 1、保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。 2. 所有新增内容必须源于历史对话或聊天背景,禁止捏造。 -3. 归一化替换需严格全词匹配:查询中的词必须与术语库同义词完全一致(不区分大小写)。部分匹配(如子字符串)或不匹配,保留原词 - 禁止部分匹配或子字符串替换。仅当提问中的词 **完全等于** 术语库同义词(大小写不敏感)时方可替换,否则保留原词。 - - 错误示例:`文件` ≠ `文件夹路径`(因`文件`是`文件夹路径`的子字符串,禁止替换)。 +3. 归一化替换需严格全词匹配:查询中的词必须与术语库同义词完全一致(不区分大小写)。部分匹配(如子字符串)或不匹配,保留原词 ## 核心原则 1. **指代消除 → 当指示代词("那"/"这")出现时,强制继承历史对话的最新核心主题(如功能或任务),并应用到当前主体。** 2. 背景继承 → 补充历史对话和聊天背景中的隐含信息(包括主题和功能)。 -3. 术语规范 → 归一化标准词并【】标记。提问中出现的同义词(synonymous)替换为标准词(name), +3. 术语规范 → 提问中出现的同义词(synonymous)替换为标准词(name)并【】标记 4. 语义保真 → 保持问题核心意图,但允许在指代消除、背景继承下添加隐含功能词。 ## 归一化替换规则 -1. 必须严格全词匹配同义词(即synonymous全词出现在query中) - “错误示例: - - query:文件 !=> 文件夹路径(‘文件’不全等于‘文件夹路径’,部分匹配不替换)。 - - query:费率查询 !=> 精准查询(‘费率查询’不全等于‘关键词查询’,不替换)。 - **仅当全词匹配时替换**:如query:直接费率(全词匹配‘直接费率’)==> 固定费率。” -2. 只有当问题中的词与术语库中某一项的同义词列表中的某个词完全相同时,才替换为对应的标准词 +1. 只有当问题中的词与术语库中某一项的同义词列表中的某个词完全相同时,才替换为对应的标准词 ## 处理流程 @@ -211,11 +204,6 @@ query_rewrite_prompt_pro=""" {chat_history} - - - 当前聊天背景: - - {context} - ### 二、重构决策树 ```mermaid @@ -227,7 +215,7 @@ graph TD E --> F[执行重构] D -- 否 --> F F --> G[补充缺失背景] - G --> H[同义词替换+【】标记] + G --> H[同义词替换] H --> I[保留原生专业术语] B -- 否 --> I ``` @@ -235,9 +223,8 @@ graph TD ### 三、重构优先级 1. **指代消除 → 当指示代词出现时,优先继承历史对话的核心主题(如功能词),并替换当前问题的动词部分。** 2. 背景继承 → 历史对话中确定的背景信息需要保留。 -3. 术语处理 → 同义词转标准词 + 【】标记。 -4. 同义词转标准词 → 将提问中出现的同义词(synonymous)替换为对应标准词(name) -5. 结构优化 → 保持原问题的5W2H特征,指代消除、背景继承下允许微调意图。 +3. 同义词转标准词 → 将提问中出现的同义词(synonymous)替换为对应标准词(name) 并使用【】标记 +4. 结构优化 → 保持原问题的5W2H特征,指代消除、背景继承下允许微调意图。 ## 输出规范 {output_format} @@ -246,7 +233,6 @@ graph TD - [] **主题是否合理继承?**(当有代词时,历史主题必须注入) - [] 核心诉求是否保留? - [] 背景信息是否合理补充? -- [] 术语标记是否完整【】? - [] 语句是否自然流畅? - [] 避免补充无关信息 """