|
|
|
@ -9,45 +9,67 @@ from Config import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class KnowledgeGraph:
|
|
|
|
|
def __init__(self, shiti_content: str):
|
|
|
|
|
self.shiti_content = shiti_content
|
|
|
|
|
def __init__(self, content: str):
|
|
|
|
|
self.content = content
|
|
|
|
|
self.client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_API_URL)
|
|
|
|
|
self.question_id = self._generate_question_id()
|
|
|
|
|
|
|
|
|
|
def _generate_question_id(self) -> str:
|
|
|
|
|
"""生成题目唯一标识符"""
|
|
|
|
|
return hashlib.md5(self.shiti_content.encode()).hexdigest()[:8]
|
|
|
|
|
return hashlib.md5(self.content.encode()).hexdigest()[:8]
|
|
|
|
|
|
|
|
|
|
def _generate_stream(self) -> Iterator[ChatCompletionChunk]:
|
|
|
|
|
"""流式生成内容(优化约束和MERGE)"""
|
|
|
|
|
system_prompt = f'''
|
|
|
|
|
一、总结本题有哪些知识点和能力点。
|
|
|
|
|
二、将总结出的知识点,能力点等信息,按以下要求生成Neo4j 5.26+的Cypher语句:
|
|
|
|
|
1. 必须包含约束创建:
|
|
|
|
|
CREATE CONSTRAINT IF NOT EXISTS FOR (kp:KnowledgePoint) REQUIRE kp.id IS UNIQUE;
|
|
|
|
|
CREATE CONSTRAINT IF NOT EXISTS FOR (ab:AbilityPoint) REQUIRE ab.id IS UNIQUE;
|
|
|
|
|
|
|
|
|
|
2. 节点使用MERGE并包含唯一ID:
|
|
|
|
|
// 知识点节点
|
|
|
|
|
MERGE (kp:KnowledgePoint {{id: "KP_101"}})
|
|
|
|
|
SET kp.name = "长方形周长计算",
|
|
|
|
|
kp.level = "小学"
|
|
|
|
|
|
|
|
|
|
// 题目节点(使用生成的ID:{self.question_id})
|
|
|
|
|
MERGE (q:Question {{id: "{self.question_id}"}})
|
|
|
|
|
SET q.content = "巧求周长:7个相同小长方形拼图求周长",
|
|
|
|
|
q.difficulty = 3
|
|
|
|
|
|
|
|
|
|
3. 关系基于已存在节点:
|
|
|
|
|
MATCH (q:Question {{id: "{self.question_id}"}}), (kp:KnowledgePoint {{id: "KP_101"}})
|
|
|
|
|
MERGE (q)-[r:TESTS_KNOWLEDGE]->(kp)
|
|
|
|
|
SET r.weight = 0.8'''
|
|
|
|
|
"""动态化提示词版本"""
|
|
|
|
|
system_prompt = f'''请根据题目内容生成Neo4j Cypher语句,严格遵循以下规则:
|
|
|
|
|
# 节点创建规范
|
|
|
|
|
1. 知识点节点:
|
|
|
|
|
- 标签: KnowledgePoint
|
|
|
|
|
- 必须属性:
|
|
|
|
|
* id: "KP_" + 知识点名称的MD5前6位(示例:name="分数运算" → id="KP_ae3b8c")
|
|
|
|
|
* name: 知识点名称(从题目内容中提取)
|
|
|
|
|
* level: 学段(小学/初中/高中)
|
|
|
|
|
|
|
|
|
|
2. 能力点节点:
|
|
|
|
|
- 标签: AbilityPoint
|
|
|
|
|
- 必须属性:
|
|
|
|
|
* id: "AB_" + 能力名称的MD5前6位
|
|
|
|
|
* name: 能力点名称
|
|
|
|
|
* category: 能力类型(计算/推理/空间想象等)
|
|
|
|
|
|
|
|
|
|
3. 题目节点:
|
|
|
|
|
- 标签: Question
|
|
|
|
|
- 必须属性:
|
|
|
|
|
* id: "{self.question_id}"(已根据题目内容生成)
|
|
|
|
|
* content: 题目文本摘要(50字内)
|
|
|
|
|
* difficulty: 难度系数(1-5整数)
|
|
|
|
|
|
|
|
|
|
# 关系规则
|
|
|
|
|
1. 题目与知识点关系:
|
|
|
|
|
(q:Question)-[:TESTS_KNOWLEDGE]->(kp:KnowledgePoint)
|
|
|
|
|
需设置权重属性 weight(0.1-1.0)
|
|
|
|
|
|
|
|
|
|
2. 题目与能力点关系:
|
|
|
|
|
(q:Question)-[:REQUIRES_ABILITY]->(ab:AbilityPoint)
|
|
|
|
|
需设置权重属性 weight
|
|
|
|
|
|
|
|
|
|
# 生成步骤
|
|
|
|
|
1. 先创建约束(必须):
|
|
|
|
|
CREATE CONSTRAINT IF NOT EXISTS FOR (kp:KnowledgePoint) REQUIRE kp.id IS UNIQUE;
|
|
|
|
|
CREATE CONSTRAINT IF NOT EXISTS FOR (ab:AbilityPoint) REQUIRE ab.id IS UNIQUE;
|
|
|
|
|
|
|
|
|
|
2. 使用MERGE创建节点(禁止使用CREATE)
|
|
|
|
|
|
|
|
|
|
3. 最后创建关系(需先MATCH已存在节点)
|
|
|
|
|
|
|
|
|
|
# 当前题目信息
|
|
|
|
|
- 生成的问题ID: {self.question_id}
|
|
|
|
|
- 题目内容: "{self.content[:50]}..."(已截断)'''
|
|
|
|
|
|
|
|
|
|
return self.client.chat.completions.create(
|
|
|
|
|
model=MODEL_NAME,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": system_prompt},
|
|
|
|
|
{"role": "user", "content": self.shiti_content}
|
|
|
|
|
{"role": "user", "content": self.content}
|
|
|
|
|
],
|
|
|
|
|
stream=True,
|
|
|
|
|
timeout=300
|
|
|
|
@ -76,7 +98,6 @@ SET r.weight = 0.8'''
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
|
|
|
content_buffer = []
|
|
|
|
|
cypher_script = ""
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
print(f"🚀 开始生成知识点和能力点的总结和插入语句")
|
|
|
|
|