Files
zoujiwen 517691c2d6 上传文件至 kg_lab_6.13
6.18 更新数据配置路径统一,和前端demo
2025-06-18 16:02:47 +08:00

231 lines
8.1 KiB
Python

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
from extraction_info import neo4j_url, neo4j_username, neo4j_password
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 Problem_rewrite():
PromptTemplate1 = """
请根据用户的输入内容,替换其中内容:
【用户输入】:
{query}
【检索内容】:
{retriever}
【举例】:
用户输入:塔材装材费是多少?
检索内容:角钢塔_塔材装材费_元
得到的结果:【角钢塔_塔材装材费_元】是多少?
【要求】:
- 不允许输出任何解释、标点符号或额外内容,仅在原输入上进行替换
- 替换后的内容要加上【】
"""
Prompt = ChatPromptTemplate.from_template(PromptTemplate1)
Chain = Prompt | deep_v3 | StrOutputParser()
# Chain = Prompt | llm | StrOutputParser()
return Chain
def question_answer():
PromptTemplate1 = """
请根据用户的输入内容,和检索到的信息,回答问题:
【用户输入】:
{query}
【实际检索目标】:
{retriever_keywords}
【检索内容】:
{retriever_info}
【要求】:
- 不允许输出任何解释、标点符号或额外内容
- 要选找到和实际检索目标最接近的检索内容,直接读取相关信息进行解答,不做任何运算
- 检索到的信息不一定有用,如果和问题毫无相关性,则回答不会
"""
Prompt = ChatPromptTemplate.from_template(PromptTemplate1)
Chain = Prompt | deep_v3 | StrOutputParser()
# Chain = Prompt | llm | StrOutputParser()
return Chain
def question_answer_calculation():
PromptTemplate1 = """
请根据用户的实际检索目标查到的内容,基于用户输入和计算公式回答问题:
【用户输入】:
{query}
【实际检索目标】:
{retriever_keywords}
【计算公式】:
{calculation}
【检索内容】:
{retriever_info}
【要求】:
- 不允许输出任何解释、标点符号或额外内容
- 要选找到和实际检索目标最接近的检索内容,直接读取相关信息进行解答,不做任何运算
- 检索到的信息不一定有用,如果和问题毫无相关性,则回答不会
"""
Prompt = ChatPromptTemplate.from_template(PromptTemplate1)
Chain = Prompt | deep_v3 | StrOutputParser()
# Chain = Prompt | llm | StrOutputParser()
return Chain
"""neo4j"""
from langchain_community.graphs import Neo4jGraph
graph = Neo4jGraph(
url = neo4j_url,
username = neo4j_username,
password = neo4j_password,
)
graph.refresh_schema()
from langchain.prompts import (
PromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
ChatPromptTemplate,
)
cypher_generation_template = """
# 任务:
为 Neo4j 图数据库生成 Cypher 查询。
# 说明:
仅使用架构中提供的关系类型和属性。 不得使用架构中未提供的关系类型或属性。
# 架构:
{schema}
# 注意:
不得在回答中包含任何解释或道歉。
不得回答任何不要求构造 Cypher 查询的问题。
回答中不得包含除生成的 Cypher 查询以外的任何文本。
请确保查询中关系的方向正确,并正确为实体和关系设置别名。
在查询中使用 WITH 为后续语句设置别名(例如,WITH v as visit, c.billing_amount as billing_amount)。
如果需要进行数字除法运算,请确保对分母进行非零过滤。
# 注意
在查询关键字时,不能使用MATCH (n:PropertyNode),要用最原始的MATCH (n)
在查询中分析缺失属性时,必须使用 IS NULL 或 IS NOT NULL。
不得在查询中返回嵌套属性。
不得在查询中包含 "GROUP BY" 语句。
请确保为所有后续语句使用 WITH 设置别名(例如,WITH v as visit, c.billing_amount as billing_amount)。
如果需要进行数字除法运算,请确保对分母进行非零过滤。
# 示例:
1.
输入:
查找一下【工程数据/安装工程/安装/架空输电线路本体工程/基础工程】的【定额】下的【YX2-1/YX2-2/YX2-3/YX2-4/YX2-5/YX2-6/YX2-7】
输出:
MATCH (root:ProjectDivisionItem [name: '架空输电线路本体工程'])-[:HAS_CHILD]->(base:ProjectDivisionItem [name: '基础工程'])
MATCH path = (base)-[:HAS_CHILD]->(child)-[:HAS_COMPONENT*1..]->(component)
WHERE ANY(prop IN keys(component) WHERE toString(component[prop]) =~ 'YX2-[1-7]')
RETURN component
2.
输入:
查找一下【工程数据/安装工程/安装/架空输电线路本体工程/杆塔工程/杆塔组立/铁塔、钢管杆组立】的【主材】下的【角钢】
输出:
MATCH (root:ProjectDivisionItem [name: '架空输电线路本体工程'])-[:HAS_CHILD]->(base1:ProjectDivisionItem [name: '杆塔工程'])-[:HAS_CHILD]->(base2:ProjectDivisionItem [name: '杆塔组立'])-[:HAS_CHILD]->(base3:ProjectDivisionItem [name: '铁塔、钢管杆组立'])
MATCH path = (base3)-[:HAS_COMPONENT*1..]->(component)
WHERE ANY(prop IN keys(component) WHERE toString(component[prop]) CONTAINS '角钢')
RETURN component
3.
输入:
查找一下【架空输电线路本体工程/架线工程/导地线架设】和【架空输电线路本体工程/架线工程/导地线跨越架设】的【主材】下的【高导电率】
输出:
MATCH (root:ProjectDivisionItem [name: '架空输电线路本体工程'])
-[:HAS_CHILD]->(base1:ProjectDivisionItem [name: '架线工程'])-[:HAS_CHILD]->(base:ProjectDivisionItem)
WHERE base.name IN ['导地线架设', '导地线跨越架设']
MATCH path = (base)-[:HAS_COMPONENT*1..]->(component)
WHERE ANY(prop IN keys(component) WHERE toString(component[prop]) CONTAINS '高导电率')
RETURN component
问题:
{question}
"""
cypher_generation_prompt = PromptTemplate(
input_variables=["schema", "question"], template=cypher_generation_template
)
qa_generation_template = """你是一个助手,根据 Neo4j Cypher 查询的结果生成可读的回答。查询结果部分包含根据用户的自然语言问题生成的 Cypher 查询结果。提供的信息是权威的;你必须始终使用这些信息来构建回答,不得使用内部知识来质疑或更正这些信息。确保回答听起来像是对问题的直接回应。
用户提出了以下问题:
{question}
运行了一个 Cypher 查询,生成了以下结果:
{context}
如果提供的信息是空的,就说明你不知道答案。
空的信息看起来是这样的:[]
如果查询结果不为空,你必须提供一个回答。
如果有查询结果数据,绝不能说你没有正确的信息。如果用户提问时需要显示所有相关查询结果,确保你显示所有相关结果。你必须始终假设提供的查询结果与问题相关。回答时只能基于提供的查询结果构建答案。
"""
qa_generation_prompt = PromptTemplate(
input_variables=["context", "question"], template=qa_generation_template
)
from langchain.chains import GraphCypherQAChain
booway_cypher_chain = GraphCypherQAChain.from_llm(
allow_dangerous_requests=True,
cypher_llm=deep_v3, # 用于生成Cypher查询的LLM
qa_llm=deep_v3, # 用于根据Cypher查询结果生成答案的LLM
graph=graph,
verbose=True,
qa_prompt=qa_generation_prompt,
cypher_prompt=cypher_generation_prompt,
validate_cypher=True,
top_k=100,
return_intermediate_steps=True
)