From d0261c599753dc5a6e9a8e6c603b8d8f7e62e4f0 Mon Sep 17 00:00:00 2001 From: zoujiwen Date: Thu, 3 Apr 2025 17:23:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4.3更新 --- chains_ceshi.py | 735 ++++++++++++++++++++++++++-------------------- chains_rewrite.py | 97 ++++++ fast_api_main.py | 328 +++++++++++---------- 3 files changed, 674 insertions(+), 486 deletions(-) diff --git a/chains_ceshi.py b/chains_ceshi.py index 9587638..9947ec1 100644 --- a/chains_ceshi.py +++ b/chains_ceshi.py @@ -1,324 +1,413 @@ -""" -=================================== -@Auther:WenZ -@Company: BooWay -@project:booway_dm -=================================== -""" - - -# from langchain_community.chat_models import ChatOpenAI -from langchain_openai import ChatOpenAI -from langchain_core.output_parsers import StrOutputParser -from langchain_core.prompts import ChatPromptTemplate -from langchain_core.prompts.prompt import PromptTemplate -from langchain_core.output_parsers import JsonOutputParser - - -# qwen_llm = ChatOpenAI(model='deepseek-qwen2.5-32b',base_url="http://172.20.0.145:9995/v1/",api_key='233',temperature=1) - -# temperature=0.7 -qwen_llm = ChatOpenAI( - openai_api_base="https://api.siliconflow.cn/v1", - model_name="Qwen/Qwen2.5-72B-Instruct", - # sk-muuqautpcyuowjtgfecbnivqodlhzydtfslqkmwbknawejsx - openai_api_key="sk-bbeamiumkouptsrueilgufqqyuumelcsivxwjbdugqwsqhwj", - temperature=0.1 -) - -deep_v3 = ChatOpenAI( - openai_api_base="https://api.siliconflow.cn/v1", - model_name="deepseek-ai/DeepSeek-V3", - # sk-muuqautpcyuowjtgfecbnivqodlhzydtfslqkmwbknawejsx - openai_api_key="sk-bbeamiumkouptsrueilgufqqyuumelcsivxwjbdugqwsqhwj", - temperature=0.1 -) - - -def suffix_answers(): - PromptTemplate1 = """ - 根据用户输入和相关知识回答问题 - - # 用户输入 - {query} - - # 相关知识 - {kg} - - # 注意: - - 每次回答和核心意思是:'此后缀名文件用某某或哪些软件打开' - - 对于相关知识中有多个软件的要全部回答 - - 不要有过多解释,仅仅根据kg回答即可 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - -# 关于下载安装 -# 查询功能(询问软件功能或用途):【新型储能计价通C1】可以做批次工程吗 -# 后缀名问题(专属子意图) -# 操作指导(询问具体使用方法):【西藏造价软件Z1】怎么查看人工机械费用 -# 故障排查(解决软件错误问题):【技改检修2016软件】初始化失败了 -# 费用计算(专属意图,复杂计算推理) -# 下载与安装(询问软件的下载和安装):【配网D3软件】程序包发我;【配网D3软件】怎么安装 - -def Vertical_classification(): - PromptTemplate1 = """ - 根据用户输入进行垂直领域分类 - - 目前的垂直分类:【'闲聊', '软件咨询'】 - - # 软件咨询包括以下: - 1. 查询功能(询问软件功能或用途,包括后缀名问题) - 2. 操作指导(询问具体使用方法) - 3. 故障排查(解决软件错误问题) - 4. 下载安装(关于软件的下载和安装问题) - - # 用户输入 - {query} - - # 注意: - 1. 你只能回答是'闲聊' 或者 '软件咨询',绝对不能有其他回复 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - -# chain_vertical = Vertical_classification() - - -def small_talk(): - PromptTemplate1 = """ - 你是一个开放性的聊天助手,请以礼貌的方式进行回复 - - # 用户输入 - {query} - - # 注意 - 1. 对于用户发送类似“你好”、“hi”、“嗨”之类的问候语,需要固定回复:“您好,尊贵的VIP,我是booway小助手,很高兴为您服务” - 2. 对于用户发送类似“你是谁”、“你能干什么”、“你有什么功能”之类的询问身份和功能的语句,需要固定回复:“您好,我是booway小助手,如您需要相关电力造价软件的使用咨询,可以和我沟通” - 3. 初次之外的聊天,不需要告知用户的身份和你的身份 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - - -# chain_small_talk = small_talk() - - -# 查询功能(询问软件功能或用途):【新型储能计价通C1】可以做批次工程吗 -# 后缀名问题(专属子意图) -# 操作指导(询问具体使用方法):【西藏造价软件Z1】怎么查看人工机械费用 -# 故障排查(解决软件错误问题):【技改检修2016软件】初始化失败了 -# 费用计算(专属意图,复杂计算推理) -# 下载与安装(询问软件的下载和安装):【配网D3软件】程序包发我;【配网D3软件】怎么安装 -def intention_judge(): - # 费用计算另处理 - PromptTemplate1 = """ - 你是一个智能意图分类助手。请根据用户的问题,将其归类到以下意图中: - - 1. 查询功能(询问软件功能或用途) - 2. 操作指导(询问具体使用方法) - 3. 故障排查(解决软件错误问题) - 4. 下载安装(关于软件的下载和安装问题) - - 用户的问题是:"{query}" - - 请明确指出该问题属于哪个意图类别。 - - 输出格式:str类型 - - 注意你的回复答案一定是[查询功能、操作指导、故障排查、下载安装]之一,不要有其他回答,不要解释说明 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - - -def domain_judge(): - # 费用计算另处理 - PromptTemplate1 = """ - 你是一个领域问题分类助手。请根据用户的问题,将其归类到以下软件领域中: - - 1. 西藏造价软件Z1 - 2. 新型储能计价通C1 - 3. 技改检修计价通T1 - 4. 未知 (用户输入没有提到具体软件名称,就回答‘未知’) - - 用户输入:"{query}" - - 请明确指出该问题属于哪个领域问题分类。 - - 输出格式:str类型 - - 注意: - 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、未知]之一,不要有其他回答,不要解释说明 - 2. 如果用户输入没有说明具体哪个软件,则回答‘未知’ - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | deep_v3 | StrOutputParser() - - return Chain - -def domain_judge_v2(): - # 费用计算另处理 - PromptTemplate1 = """ - 你是一个不全软件名称的助手。请根据用户的问题,进行补全: - - 1. 西藏造价软件Z1 - 2. 新型储能计价通C1 - 3. 技改检修计价通T1 - 4. 未知 (用户输入没有提到具体软件名称,就回答‘未知’) - - 用户输入:"{query}" - - 输出格式:str类型 - - 注意: - 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、未知]之一,不要有其他回答,不要解释说明 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | deep_v3 | StrOutputParser() - - return Chain - - -def judge_5W2H(): - PromptTemplate1 = """ - 你是一位专业的语言分析师。请根据以下输入,识别出它属于5W2H中的哪一类: - - What: 表示“什么”。 - - Why: 表示“为什么”。 - - When: 表示“什么时候”。 - - Where: 表示“在哪里”。 - - Who: 表示“谁”。 - - How: 表示“如何”。 - - How much: 表示“多少”。 - - 输入: {query} - 请判断并仅返回类别名称。 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - - -def extract_keywords(): - PromptTemplate1 = """ - 你是一位专业的语言分析师。请根据以下输入内容,精准提取“需求”部分: - - 软件名称:{software_name} - 5W2H 类型:{_5w2h_type} - 用户输入:{query} - - 提取规则: - 仅提取用户输入中,除软件名称和5W2H类型以外的“需求”部分,保持原意简洁输出,不添加解释或思考过程。 - - 示例1: - 软件名称:新型储能计价通C1 - 5W2H 类型:How - 用户输入:储能软件,怎么批量将乙供主材改为甲供 - 输出:批量将乙供主材改为甲供 - - 示例2: - 软件名称:西藏造价软件Z1 - 5W2H 类型:What - 用户输入:西藏Z1软件,海报高度选择不同影响什么 - 输出:海报高度选择不同影响什么 - - 注意事项: - - 输出仅包含“需求”内容 - - “需求”需要你根据语义总结 - - 不要输出任何解释或推理过程 - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | qwen_llm | StrOutputParser() - - return Chain - -# def answer_questions(): -# PromptTemplate1 = """ -# 你是一个回答助手,请根据检索到的知识内容来回答用户的问题。 -# -# # 用户问题: -# {query} -# -# # 检索到的知识内容: -# {kg} -# -# # 回答要求: -# 1. 仅依据检索到的知识内容进行回答,不要引入任何其他未提供的知识。 -# 2. 如果检索内容中仅有部分信息与你判断相关,请结合有用部分作答,忽略无关内容。 -# 3. 如果你无法根据检索内容推理或回答用户问题,请回答:“没有相关知识”。 -# -# """ -# -# Prompt = ChatPromptTemplate.from_template(PromptTemplate1) -# -# Chain = Prompt | deep_v3 | StrOutputParser() -# -# return Chain - -def answer_questions(): - PromptTemplate1 = """ - 请严格根据以下框架回答用户问题: - - # 用户问题: - {query} - - # 检索到的知识内容: - {kg} - - # 回答规则 (必须逐条遵守): - 1. 相关性优先原则 - - 必须严格检查检索内容与用户问题的相关性 - - 仅当检索内容中存在至少一条与问题直接相关的明确证据时,才允许作答 - - 若检索内容整体与问题无关,即使内容正确,也必须回答"没有相关知识" - - 2. 精准引用原则 - - 回答必须完全基于检索内容中的有效证据 - - 禁止添加任何外部知识、常识推理或主观猜测 - - 禁止对检索内容进行延伸解读,仅允许直接相关的事实陈述 - - 3. 部分相关处理 - - 当检索内容中只有部分段落相关时: - 1. 先验证该段落是否直接对应问题核心 - 2. 确认无误后仅使用该部分作答 - 3. 主动忽略其他无关内容 - - 4. 拒绝回答场景 - - 检索内容与问题无逻辑关联时 - - 需要连接多个非直接相关片段进行推理时 - - 存在相关表述但缺乏明确证据支持时 - - # 回答要求 - 1. 基于以上回答规则,仅做回答,不要加上思考过程 - - """ - - Prompt = ChatPromptTemplate.from_template(PromptTemplate1) - - Chain = Prompt | deep_v3 | StrOutputParser() - +""" +=================================== +@Auther:WenZ +@Company: BooWay +@project:booway_dm +=================================== +""" + + +# from langchain_community.chat_models import ChatOpenAI +from langchain_openai import ChatOpenAI +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.prompts.prompt import PromptTemplate +from langchain_core.output_parsers import JsonOutputParser + + +# qwen_llm = ChatOpenAI(model='deepseek-qwen2.5-32b',base_url="http://172.20.0.145:9995/v1/",api_key='233',temperature=1) + +# temperature=0.7 +qwen_llm = ChatOpenAI( + openai_api_base="https://api.siliconflow.cn/v1", + model_name="Qwen/Qwen2.5-72B-Instruct", + # sk-muuqautpcyuowjtgfecbnivqodlhzydtfslqkmwbknawejsx + openai_api_key="sk-bbeamiumkouptsrueilgufqqyuumelcsivxwjbdugqwsqhwj", + temperature=0.1 +) + +deep_v3 = ChatOpenAI( + openai_api_base="https://api.siliconflow.cn/v1", + model_name="deepseek-ai/DeepSeek-V3", + # sk-muuqautpcyuowjtgfecbnivqodlhzydtfslqkmwbknawejsx + openai_api_key="sk-bbeamiumkouptsrueilgufqqyuumelcsivxwjbdugqwsqhwj", + temperature=0.1 +) + + +# from langchain.llms import Xinference +# from langchain.prompts import PromptTemplate +# from langchain.chains import LLMChain, SequentialChain + +# llm = Xinference(server_url="http://172.20.0.145:9995", model_uid="deepseek-r1-distill-qwen2.5-32b") + + +def suffix_answers(): + PromptTemplate1 = """ + 根据用户输入和相关知识回答问题 + + # 用户输入 + {query} + + # 相关知识 + {kg} + + # 注意: + - 每次回答和核心意思是:'此后缀名文件用某某或哪些软件打开' + - 对于相关知识中有多个软件的要全部回答 + - 不要有过多解释,仅仅根据kg回答即可 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +# 关于下载安装 +# 查询功能(询问软件功能或用途):【新型储能计价通C1】可以做批次工程吗 +# 后缀名问题(专属子意图) +# 操作指导(询问具体使用方法):【西藏造价软件Z1】怎么查看人工机械费用 +# 故障排查(解决软件错误问题):【技改检修2016软件】初始化失败了 +# 费用计算(专属意图,复杂计算推理) +# 下载与安装(询问软件的下载和安装):【配网D3软件】程序包发我;【配网D3软件】怎么安装 + +# def Vertical_classification(): +# PromptTemplate1 = """ +# 根据用户输入进行垂直领域分类 + +# 目前的垂直分类:【'闲聊', '软件咨询'】 + +# # 软件咨询包括以下: +# 1. 查询功能(询问软件功能或用途,包括后缀名问题) +# 2. 操作指导(询问具体使用方法) +# 3. 故障排查(解决软件错误问题) +# 4. 下载安装(关于软件的下载和安装问题) + +# # 用户输入 +# {query} + +# # 注意: +# 1. 你只能回答是'闲聊' 或者 '软件咨询',绝对不能有其他回复 +# """ + +# Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + +# Chain = Prompt | qwen_llm | StrOutputParser() + +# return Chain + +def Vertical_classification(): + PromptTemplate1 = """ + 请根据用户的输入内容,将其归类为以下两个垂直领域之一: + + 【垂直领域分类】: + 1. 闲聊 —— 指与软件无关的日常对话、问候、感慨、情绪表达等。 + 2. 软件咨询 —— 指涉及软件使用、下载、功能、问题排查等方面的提问或请求。 + + 【软件咨询包括以下四类】: + 1. 查询功能:例如询问软件的功能、用途,或某种文件后缀对应的软件。 + 2. 操作指导:例如询问如何使用某个功能、软件的使用方法。 + 3. 故障排查:例如反馈软件报错、卡顿、打不开等问题,并寻求解决方案。 + 4. 下载安装:例如请求下载地址、安装流程、环境配置等信息。 + + 【用户输入】: + {query} + + 【要求】: + - 请你只返回一个结果:"闲聊" 或 "软件咨询"。 + - 不允许输出任何解释、标点符号或额外内容。 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +# chain_vertical = Vertical_classification() + + +def small_talk(): + PromptTemplate1 = """ + 你是一个开放性的聊天助手,请以礼貌的方式进行回复 + + # 用户输入 + {query} + + # 注意 + 1. 对于用户发送类似“你好”、“hi”、“嗨”之类的问候语,需要固定回复:“您好,尊贵的VIP,我是booway小助手,很高兴为您服务” + 2. 对于用户发送类似“你是谁”、“你能干什么”、“你有什么功能”之类的询问身份和功能的语句,需要固定回复:“您好,我是booway小助手,如您需要相关电力造价软件的使用咨询,可以和我沟通” + 3. 初次之外的聊天,不需要告知用户的身份和你的身份 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + # Chain = Prompt | llm | StrOutputParser() + Chain = Prompt | qwen_llm | StrOutputParser() + + return Chain + + +# chain_small_talk = small_talk() + + +# 查询功能(询问软件功能或用途):【新型储能计价通C1】可以做批次工程吗 +# 后缀名问题(专属子意图) +# 操作指导(询问具体使用方法):【西藏造价软件Z1】怎么查看人工机械费用 +# 故障排查(解决软件错误问题):【技改检修2016软件】初始化失败了 +# 费用计算(专属意图,复杂计算推理) +# 下载与安装(询问软件的下载和安装):【配网D3软件】程序包发我;【配网D3软件】怎么安装 +def intention_judge(): + # 费用计算另处理 + PromptTemplate1 = """ + 你是一个智能意图分类助手。请根据用户的问题,将其归类到以下意图中: + + 1. 查询功能(询问软件功能或用途) + 2. 操作指导(询问具体使用方法) + 3. 故障排查(解决软件错误问题) + 4. 下载安装(关于软件的下载和安装问题) + + 用户的问题是:"{query}" + + 请明确指出该问题属于哪个意图类别。 + + 输出格式:str类型 + + 注意你的回复答案一定是[查询功能、操作指导、故障排查、下载安装]之一,不要有其他回答,不要解释说明 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + + +def domain_judge(): + # 费用计算另处理 + PromptTemplate1 = """ + 你是一个领域问题分类助手。请根据用户的问题,将其归类到以下软件领域中: + + 1. 西藏造价软件Z1 + 2. 新型储能计价通C1 + 3. 技改检修计价通T1 + 4. 未知 (用户输入没有提到具体软件名称,就回答‘未知’) + + 用户输入:"{query}" + + 请明确指出该问题属于哪个领域问题分类。 + + 输出格式:str类型 + + 注意: + 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、未知]之一,不要有其他回答,不要解释说明 + 2. 如果用户输入没有说明具体哪个软件,则回答‘未知’ + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +def domain_judge_v2(): + # 费用计算另处理 + PromptTemplate1 = """ + 你是一个不全软件名称的助手。请根据用户的问题,进行补全: + + 1. 西藏造价软件Z1 + 2. 新型储能计价通C1 + 3. 技改检修计价通T1 + 4. 未知 (用户输入没有提到具体软件名称,就回答‘未知’) + + 用户输入:"{query}" + + 输出格式:str类型 + + 注意: + 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、未知]之一,不要有其他回答,不要解释说明 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +def domain_judge_v3(): + # 费用计算另处理 + PromptTemplate1 = """ + 你是一个领域问题分类助手。请根据用户的问题,将其归类到以下软件领域中: + + 1. 西藏造价软件Z1 + 2. 新型储能计价通C1 + 3. 技改检修计价通T1 + 4. 博微配网工程计价通D3软件 + 5. 其他 (用户输入没有提到具体软件名称或者不属于上述软件名,就回答‘其他’) + + 用户输入:"{query}" + + 请明确指出该问题属于哪个领域问题分类。 + + 输出格式:str类型 + + 注意: + 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、博微配网工程计价通D3软件、未知]之一,不要有其他回答,不要解释说明 + 2. 如果用户输入没有说明具体哪个软件,则回答‘其他’ + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + + +def judge_5W2H(): + PromptTemplate1 = """ + 你是一位专业的语言分析师。请根据以下输入,识别出它属于5W2H中的哪一类: + - What: 表示“什么”。 + - Why: 表示“为什么”。 + - When: 表示“什么时候”。 + - Where: 表示“在哪里”。 + - Who: 表示“谁”。 + - How: 表示“如何”。 + - How much: 表示“多少”。 + + 输入: {query} + 请判断并仅返回类别名称。 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + + +def extract_keywords(): + PromptTemplate1 = """ + 你是一位专业的语言分析师。请根据以下输入内容,精准提取“需求”部分: + + 软件名称:{software_name} + 5W2H 类型:{_5w2h_type} + 用户输入:{query} + + 提取规则: + 仅提取用户输入中,除软件名称和5W2H类型以外的“需求”部分,保持原意简洁输出,不添加解释或思考过程。 + + 示例1: + 软件名称:新型储能计价通C1 + 5W2H 类型:How + 用户输入:储能软件,怎么批量将乙供主材改为甲供 + 输出:批量将乙供主材改为甲供 + + 示例2: + 软件名称:西藏造价软件Z1 + 5W2H 类型:What + 用户输入:西藏Z1软件,海报高度选择不同影响什么 + 输出:海报高度选择不同影响什么 + + 注意事项: + - 输出仅包含“需求”内容 + - “需求”需要你根据语义总结 + - 不要输出任何解释或推理过程 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +# def answer_questions(): +# PromptTemplate1 = """ +# 你是一个回答助手,请根据检索到的知识内容来回答用户的问题。 +# +# # 用户问题: +# {query} +# +# # 检索到的知识内容: +# {kg} +# +# # 回答要求: +# 1. 仅依据检索到的知识内容进行回答,不要引入任何其他未提供的知识。 +# 2. 如果检索内容中仅有部分信息与你判断相关,请结合有用部分作答,忽略无关内容。 +# 3. 如果你无法根据检索内容推理或回答用户问题,请回答:“没有相关知识”。 +# +# """ +# +# Prompt = ChatPromptTemplate.from_template(PromptTemplate1) +# +# Chain = Prompt | deep_v3 | StrOutputParser() +# +# return Chain + +def answer_questions(): + PromptTemplate1 = """ + 请严格根据以下框架回答用户问题: + + # 用户问题: + {query} + + # 检索到的知识内容: + {kg} + + # 回答规则 (必须逐条遵守): + 1. 相关性优先原则 + - 必须严格检查检索内容与用户问题的相关性 + - 仅当检索内容中存在至少一条与问题直接相关的明确证据时,才允许作答 + - 若检索内容整体与问题无关,即使内容正确,也必须回答"没有相关知识" + + 2. 精准引用原则 + - 回答必须完全基于检索内容中的有效证据 + - 禁止添加任何外部知识、常识推理或主观猜测 + - 禁止对检索内容进行延伸解读,仅允许直接相关的事实陈述 + + 3. 部分相关处理 + - 当检索内容中只有部分段落相关时: + 1. 先验证该段落是否直接对应问题核心 + 2. 确认无误后仅使用该部分作答 + 3. 主动忽略其他无关内容 + + 4. 拒绝回答场景 + - 检索内容与问题无逻辑关联时 + - 需要连接多个非直接相关片段进行推理时 + - 存在相关表述但缺乏明确证据支持时 + + # 回答要求 + 1. 基于以上回答规则,仅做回答,不要加上思考过程 + + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + +def mutil12(): + PromptTemplate1 = """ + 你根据输入语句:{query}来分析是缺软件名字还是缺具体问题 + # 输出 + 缺软件名字返回1 + 缺具体问题返回2 + 你只能返回1或者2,不要有其他解释 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + return Chain \ No newline at end of file diff --git a/chains_rewrite.py b/chains_rewrite.py index 22f4b7f..9490ca4 100644 --- a/chains_rewrite.py +++ b/chains_rewrite.py @@ -33,6 +33,12 @@ deep_v3 = ChatOpenAI( temperature=0.1 ) + +# ========================================= + +# ========================================= + + # 软件名重写 def software_name_rewrite(): PromptTemplate = """ @@ -47,6 +53,7 @@ def software_name_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -96,6 +103,7 @@ def retrieval_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | qwen_llm | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -114,6 +122,7 @@ def to_normal_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -134,6 +143,7 @@ def query_function_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -154,6 +164,7 @@ def operation_guidance_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -176,6 +187,7 @@ def troubleshooting_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain @@ -197,8 +209,93 @@ def access_rewrite(): Prompt = ChatPromptTemplate.from_template(PromptTemplate) Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() return Chain +# 全名扩写 +def full_name_extension(): + PromptTemplate = """ +你是一个智能问答重写助手,将用户问题和已知的软件名称重写为结构化、规范表达,符合以下范式: +1. 【软件名】【其他】 + +# 例子 +输入:D3软件二次运输怎么计取 +输出:【博微配网工程计价通D3软件】【二次运输怎么计取】 + +输入:怎么添加特征段 +输出:【】【怎么添加特征段】 + +输入:西藏造价软件Z1 +输出:【西藏造价软件Z1】【】 + +请根据以下用户问题进行规范表达,不要有任何解释说明: + +软件名称:{soft_name} +用户问题:{query} + +结构化问题: +""".strip() + + Prompt = ChatPromptTemplate.from_template(PromptTemplate) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + + +def mutil_text_rewrite(): + PromptTemplate = """ +你是一个智能问答重写助手,根据聊天记录进行结构化、规范表达的重写,符合以下范式: +1. 【软件名】【其他】 + +# 例子 +输入: +user: 西藏造价软件Z1 +assistant: 好的,具体软件是【西藏造价软件Z1】, 请补充具体的需求 +user: 进行费用统计 +输出:【西藏Z1软件】【进行费用统计】 + +请根据以下用户问题进行规范表达,不要有任何解释说明: + +聊天记录:{history} + +结构化问题: +""".strip() + + Prompt = ChatPromptTemplate.from_template(PromptTemplate) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + + +def software_judge(): + # 费用计算另处理 + PromptTemplate1 = """ + 你根据用户输入的线索来选择返回输出: + + 1. 西藏造价软件Z1 + 2. 新型储能计价通C1 + 3. 技改检修计价通T1 + 4. 博微配网工程计价通D3软件 + + 用户输入:"{query}" + + 输出格式:str类型 + + 注意: + 1. 你的回复答案一定是[西藏造价软件Z1、新型储能计价通C1、技改检修计价通T1、博微配网工程计价通D3软件]之一,不要有其他回答,不要解释说明 + """ + + Prompt = ChatPromptTemplate.from_template(PromptTemplate1) + + Chain = Prompt | deep_v3 | StrOutputParser() + # Chain = Prompt | llm | StrOutputParser() + + return Chain + diff --git a/fast_api_main.py b/fast_api_main.py index 11e40f9..ad788ef 100644 --- a/fast_api_main.py +++ b/fast_api_main.py @@ -1,163 +1,165 @@ -""" -=================================== -@Auther:WenZ -@Company: BooWay -@project:booway_dm -=================================== -""" -from utils import judge_define_suffix, match_suffix, retrieve_relevant_software -from dialogue_management import QuestionInfo, DialogType, DialogInfo, QuestionType, NLUInfo, ScenInfo, TalkInfo, \ - ChatRecord -from utils import stop_word_processing -from utils import get_keywords, get_keywords_v2, get_keywords_v3 -from vector_load import interface_search - -import spacy -import zh_core_web_sm, zh_core_web_md, zh_core_web_lg, zh_core_web_trf - -# nlp_sm = zh_core_web_sm.load() -# nlp_md = zh_core_web_md.load() -# nlp_lg = zh_core_web_lg.load() -nlp_trf = zh_core_web_trf.load() - -polite_words = {"你好", "您好", "请", "请问", "谢谢", "不客气", "麻烦", "打扰", "拜托", "辛苦", "劳驾"} - -from chains_ceshi import suffix_answers -from chains_ceshi import Vertical_classification -from chains_ceshi import intention_judge -from chains_ceshi import domain_judge -from chains_ceshi import judge_5W2H - -from chains_rewrite import software_name_rewrite -from chains_rewrite import query_function_rewrite -from chains_rewrite import operation_guidance_rewrite -from chains_rewrite import troubleshooting_rewrite -from chains_rewrite import access_rewrite - -from kg_management import retriever_txt_faiss1 -from kg_management import retriever_txt_faiss2 -from kg_management import retriever_txt_faiss3 -from kg_management import retriever_txt_faiss4 -from kg_management import retriever_txt_faiss5 -from kg_management import retriever_txt_faiss6 -from kg_management import retriever_txt_faiss7 -from kg_management import retriever_txt_faiss8 -from kg_management import retriever_txt_faiss9 - -from kg_management import input_index_csv_path -from kg_management import xizang_input_csv_path -from kg_management import cuceng_input_csv_path -from kg_management import jigai_input_csv_path - -from kg_management import process_domain_category - -domain_mapping = { - '西藏造价软件Z1': (retriever_txt_faiss1, retriever_txt_faiss2, retriever_txt_faiss3, xizang_input_csv_path), - '新型储能计价通C1': (retriever_txt_faiss4, retriever_txt_faiss5, retriever_txt_faiss6, cuceng_input_csv_path), - '技改检修计价通T1': (retriever_txt_faiss7, retriever_txt_faiss8, retriever_txt_faiss9, jigai_input_csv_path) -} - -chain_suffix_answers = suffix_answers() # 后缀名问题处理 -chain_vertical = Vertical_classification() # 垂直/开放分类 -chain_intention = intention_judge() # 意图分类 -chain_domain = domain_judge() # 领域分类 -chain_5W2H = judge_5W2H() # 5W2H分类 - -chains_name_rewrite = software_name_rewrite() # 问题改写:软件名改写 -chain_function_rewrite = query_function_rewrite() # 问题改写:软件功能查询 -chain_guidance_rewrite = operation_guidance_rewrite() # 问题改写:软件操作指导 -chain_troubleshooting_rewrite = troubleshooting_rewrite() # 问题改写:软件故障排查类 -chain_access_rewrite = access_rewrite() # 问题改写:软件下载与安装 - -from chains_rewrite import to_normal_rewrite -from chains_rewrite import retrieval_rewrite - -chain_normal_rewrite = to_normal_rewrite() -chain_retrieval_rewrite = retrieval_rewrite() - - -from utils import normalize_text - -synonym_dict = { - "费率": ["费费率"], - "下载": ["获取", "安装", "下载下来", "装上"] -} - -from fastapi import FastAPI, Request -from pydantic import BaseModel -from typing import List, Union -import uvicorn - -app = FastAPI() - -class QueryRequest(BaseModel): - input_str: str - -@app.post("/analyze") -async def analyze_input(data: QueryRequest): - input_str = data.input_str.strip() - - if judge_define_suffix(input_str): - nlu_info = NLUInfo(vertical_category="软件咨询") - nlu_info.intent_category = "查询功能" - nlu_info.domain_category = "后缀名查询" - - suffix_name = match_suffix(input_str) - nlu_info.retrieve_keywords = suffix_name - suffix_to_software = retrieve_relevant_software(suffix_name) - - if isinstance(suffix_to_software, int): - return {"response": "booway助手:未查到相关知识"} - - query_rewrite = f"{suffix_name}是什么文件?用什么软件打开?" - nlu_info.rewrite = query_rewrite - - if isinstance(suffix_to_software, list): - query_kg = '\n'.join(suffix_to_software) - else: - query_kg = suffix_to_software - - result = chain_suffix_answers.invoke({"query": input_str, "kg": query_kg}) - return {"response": f"booway助手:{result}", - "nlu_info": nlu_info} - - else: - # todo: 多轮对话处理 - input_str_stoped = stop_word_processing(input_str, nlp_trf, polite_words) # 根据实际传参调整 - input_str_syn = normalize_text(input_str_stoped, synonym_dict) - - vertical_category = chain_domain.invoke(input_str_syn) - - if vertical_category == "未知": - return {"response": "booway助手:闲聊服务只提供给内测用户"} - - nlu_info = NLUInfo(vertical_category="软件咨询") - nlu_info.domain_category = vertical_category - - input_str_name_rewrite = chains_name_rewrite.invoke({ - "query": input_str, - "software_name": nlu_info.domain_category - }) - input_str_rewrite = chain_normal_rewrite.invoke(input_str_name_rewrite) - - temp_retriever = get_keywords_v2(input_str_rewrite) - nlu_info.question_type = chain_5W2H.invoke(input_str_rewrite) - nlu_info.intent_category = chain_intention.invoke(input_str) - - retrievers, input_csv_path = domain_mapping[nlu_info.domain_category][:3], domain_mapping[nlu_info.domain_category][3] - index_keywords = interface_search(temp_retriever, *retrievers) - - nlu_info.rewrite = chain_retrieval_rewrite.invoke({ - "query": input_str_rewrite, - "question_type": nlu_info.question_type, - "intention_type": nlu_info.intent_category, - "keywords": index_keywords - }) - - nlu_info.retrieve_keywords = get_keywords_v3(nlu_info.rewrite) - - return nlu_info - -# 可选:本地调试入口 -if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=3333) +""" +=================================== +@Auther:WenZ +@Company: BooWay +@project:booway_dm +=================================== +""" +from utils import judge_define_suffix, match_suffix, retrieve_relevant_software +from dialogue_management import QuestionInfo, DialogType, DialogInfo, QuestionType, NLUInfo, ScenInfo, TalkInfo, \ + ChatRecord +from utils import stop_word_processing +from utils import get_keywords, get_keywords_v2, get_keywords_v3 +from vector_load import interface_search + +import spacy +import zh_core_web_sm, zh_core_web_md, zh_core_web_lg, zh_core_web_trf + +# nlp_sm = zh_core_web_sm.load() +# nlp_md = zh_core_web_md.load() +# nlp_lg = zh_core_web_lg.load() +nlp_trf = zh_core_web_trf.load() + +polite_words = {"你好", "您好", "请", "请问", "谢谢", "不客气", "麻烦", "打扰", "拜托", "辛苦", "劳驾"} + +from chains_ceshi import suffix_answers +from chains_ceshi import Vertical_classification +from chains_ceshi import intention_judge +from chains_ceshi import domain_judge +from chains_ceshi import judge_5W2H + +from chains_rewrite import software_name_rewrite +from chains_rewrite import query_function_rewrite +from chains_rewrite import operation_guidance_rewrite +from chains_rewrite import troubleshooting_rewrite +from chains_rewrite import access_rewrite + +from kg_management import retriever_txt_faiss1 +from kg_management import retriever_txt_faiss2 +from kg_management import retriever_txt_faiss3 +from kg_management import retriever_txt_faiss4 +from kg_management import retriever_txt_faiss5 +from kg_management import retriever_txt_faiss6 +from kg_management import retriever_txt_faiss7 +from kg_management import retriever_txt_faiss8 +from kg_management import retriever_txt_faiss9 + +from kg_management import input_index_csv_path +from kg_management import xizang_input_csv_path +from kg_management import cuceng_input_csv_path +from kg_management import jigai_input_csv_path + +from kg_management import process_domain_category + +domain_mapping = { + '西藏造价软件Z1': (retriever_txt_faiss1, retriever_txt_faiss2, retriever_txt_faiss3, xizang_input_csv_path), + '新型储能计价通C1': (retriever_txt_faiss4, retriever_txt_faiss5, retriever_txt_faiss6, cuceng_input_csv_path), + '技改检修计价通T1': (retriever_txt_faiss7, retriever_txt_faiss8, retriever_txt_faiss9, jigai_input_csv_path) +} + +chain_suffix_answers = suffix_answers() # 后缀名问题处理 +chain_vertical = Vertical_classification() # 垂直/开放分类 +chain_intention = intention_judge() # 意图分类 +chain_domain = domain_judge() # 领域分类 +chain_5W2H = judge_5W2H() # 5W2H分类 + +chains_name_rewrite = software_name_rewrite() # 问题改写:软件名改写 +chain_function_rewrite = query_function_rewrite() # 问题改写:软件功能查询 +chain_guidance_rewrite = operation_guidance_rewrite() # 问题改写:软件操作指导 +chain_troubleshooting_rewrite = troubleshooting_rewrite() # 问题改写:软件故障排查类 +chain_access_rewrite = access_rewrite() # 问题改写:软件下载与安装 + +from chains_rewrite import to_normal_rewrite +from chains_rewrite import retrieval_rewrite + +chain_normal_rewrite = to_normal_rewrite() +chain_retrieval_rewrite = retrieval_rewrite() + + +from utils import normalize_text + +synonym_dict = { + "费率": ["费费率"], + "下载": ["获取", "安装", "下载下来", "装上"] +} + +from fastapi import FastAPI, Request +from pydantic import BaseModel +from typing import List, Union +import uvicorn + +app = FastAPI() + +class QueryRequest(BaseModel): + input_str: str + +@app.post("/analyze") +async def analyze_input(data: QueryRequest): + input_str = data.input_str.strip() + + if judge_define_suffix(input_str): + nlu_info = NLUInfo(vertical_category="软件咨询") + nlu_info.intent_category = "查询功能" + nlu_info.domain_category = "后缀名查询" + + suffix_name = match_suffix(input_str) + nlu_info.retrieve_keywords = suffix_name + suffix_to_software = retrieve_relevant_software(suffix_name) + + if isinstance(suffix_to_software, int): + return {"response": "booway助手:未查到相关知识"} + + query_rewrite = f"{suffix_name}是什么文件?用什么软件打开?" + nlu_info.rewrite = query_rewrite + + if isinstance(suffix_to_software, list): + query_kg = '\n'.join(suffix_to_software) + else: + query_kg = suffix_to_software + + result = chain_suffix_answers.invoke({"query": input_str, "kg": query_kg}) + # return {"response": f"booway助手:{result}"} + return {"response": f"booway助手:{result}", + "nlu_info": nlu_info} + + else: + # todo: 多轮对话处理 + input_str_stoped = stop_word_processing(input_str, nlp_trf, polite_words) # 根据实际传参调整 + input_str_syn = normalize_text(input_str_stoped, synonym_dict) + + vertical_category = chain_domain.invoke(input_str_syn) + + if vertical_category == "未知": + return {"response": "booway助手:闲聊服务只提供给内测用户"} + + nlu_info = NLUInfo(vertical_category="软件咨询") + nlu_info.domain_category = vertical_category + + input_str_name_rewrite = chains_name_rewrite.invoke({ + "query": input_str, + "software_name": nlu_info.domain_category + }) + input_str_rewrite = chain_normal_rewrite.invoke(input_str_name_rewrite) + + temp_retriever = get_keywords_v2(input_str_rewrite) + nlu_info.question_type = chain_5W2H.invoke(input_str_rewrite) + nlu_info.intent_category = chain_intention.invoke(input_str) + + retrievers, input_csv_path = domain_mapping[nlu_info.domain_category][:3], domain_mapping[nlu_info.domain_category][3] + index_keywords = interface_search(temp_retriever, *retrievers) + + nlu_info.rewrite = chain_retrieval_rewrite.invoke({ + "query": input_str_rewrite, + "question_type": nlu_info.question_type, + "intention_type": nlu_info.intent_category, + "keywords": index_keywords + }) + + nlu_info.retrieve_keywords = get_keywords_v3(nlu_info.rewrite) + + return {"response": "success", + "nlu_info": nlu_info} + +# 可选:本地调试入口 +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=3333)