上传文件至 /

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