feat(im): mirror WeChat bot chats into AI chat as WeXin Bot conversation; add conversations.source; migrate history; remove redundant history page

This commit is contained in:
qyyfw committed 2026-07-10 10:09:49 +08:00
1 parent 7c71d193fc
commit 7b7871a14d
5 files changed
+1044 -955

No files matched your search

+96 -64
View File
@@ -691,6 +691,7 @@ def list_conversations(
"status": conv.status,
"pinned": conv.pinned,
"knowledge_graph_count": conv.knowledge_graph_count or 0,
"source": getattr(conv, "source", None),
"created_at": str(conv.created_at) if conv.created_at else None,
"updated_at": str(conv.updated_at) if conv.updated_at else None,
})
@@ -1140,69 +1141,8 @@ def clear_conversation(
return {"code": 0, "message": "对话上下文已清空"}
@router.post("/conversations/{conv_id}/to-knowledge-graph")
def convert_to_knowledge_graph(
conv_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""将对话内容转换为知识图谱"""
conv = db.query(Conversation).filter(
and_(Conversation.id == conv_id, Conversation.user_id == current_user.id)
).first()
if not conv:
raise HTTPException(status_code=404, detail="对话不存在")
messages = (
db.query(Message)
.filter(Message.conversation_id == conv_id)
.order_by(asc(Message.created_at))
.all()
)
if not messages:
raise HTTPException(status_code=400, detail="对话中没有消息, 无法生成知识图谱")
kb_name = f"对话图谱-{conv.title}"
kb = KnowledgeBase(
id=gen_uuid(),
user_id=current_user.id,
name=kb_name,
description=f"从对话「{conv.title}」自动生成的知识图谱",
directory_path="/",
document_count=0,
created_at=cst_now(),
updated_at=cst_now(),
)
db.add(kb)
db.flush()
doc_count = 0
for idx, msg in enumerate(messages):
role_label = "用户" if msg.role == "user" else "AI"
preview = re.sub(r'[\\n\\r\\t]+', ' ', msg.content[:40]).strip()
filename = f"msg_{idx+1:03d}_{role_label}_{preview}.txt"
doc = KnowledgeDocument(
id=gen_uuid(),
knowledge_base_id=kb.id,
name=filename,
filename=filename,
file_type="txt",
file_size=len(msg.content.encode('utf-8')),
content=msg.content,
status="completed",
chunk_count=max(1, len(msg.content) // 500 + 1),
created_at=cst_now(),
updated_at=cst_now(),
)
db.add(doc)
doc_count += 1
kb.document_count = doc_count
db.flush()
# 构建知识图谱节点和边
def _build_knowledge_graph(db: Session, kb: KnowledgeBase) -> dict:
"""从知识库文档构建知识图谱节点和边,返回 graph_data。"""
documents = db.query(KnowledgeDocument).filter(
and_(
KnowledgeDocument.knowledge_base_id == kb.id,
@@ -1268,7 +1208,96 @@ def convert_to_knowledge_graph(
kb.knowledge_graph_count = len(graph_nodes)
kb.updated_at = cst_now()
conv.knowledge_graph_count = (conv.knowledge_graph_count or 0) + 1
return graph_data
@router.post("/conversations/{conv_id}/to-knowledge-graph")
def convert_to_knowledge_graph(
conv_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""将对话内容转换为知识图谱(幂等:同一对话仅生成一次知识库)"""
conv = db.query(Conversation).filter(
and_(Conversation.id == conv_id, Conversation.user_id == current_user.id)
).first()
if not conv:
raise HTTPException(status_code=404, detail="对话不存在")
messages = (
db.query(Message)
.filter(Message.conversation_id == conv_id)
.order_by(asc(Message.created_at))
.all()
)
if not messages:
raise HTTPException(status_code=400, detail="对话中没有消息, 无法生成知识图谱")
# 幂等:若该对话已生成过知识图谱且知识库仍存在,则直接刷新返回
if conv.knowledge_graph_base_id:
existing_kb = db.query(KnowledgeBase).filter(
KnowledgeBase.id == conv.knowledge_graph_base_id
).first()
if existing_kb:
graph_data = _build_knowledge_graph(db, existing_kb)
conv.knowledge_graph_count = 1
conv.updated_at = cst_now()
db.commit()
return {
"code": 0,
"data": {
"knowledge_base_id": existing_kb.id,
"knowledge_base_name": existing_kb.name,
"graph": graph_data,
"knowledge_graph_count": 1,
"already_exists": True,
},
"message": "知识图谱已存在, 已刷新展示",
}
kb_name = f"对话图谱-{conv.title}"
kb = KnowledgeBase(
id=gen_uuid(),
user_id=current_user.id,
name=kb_name,
description=f"从对话「{conv.title}」自动生成的知识图谱",
directory_path="/",
document_count=0,
created_at=cst_now(),
updated_at=cst_now(),
)
db.add(kb)
db.flush()
doc_count = 0
for idx, msg in enumerate(messages):
role_label = "用户" if msg.role == "user" else "AI"
preview = re.sub(r'[\\n\\r\\t]+', ' ', msg.content[:40]).strip()
filename = f"msg_{idx+1:03d}_{role_label}_{preview}.txt"
doc = KnowledgeDocument(
id=gen_uuid(),
knowledge_base_id=kb.id,
filename=filename,
file_type="txt",
file_size=len(msg.content.encode('utf-8')),
content=msg.content,
status="completed",
chunk_count=max(1, len(msg.content) // 500 + 1),
created_at=cst_now(),
updated_at=cst_now(),
)
db.add(doc)
doc_count += 1
kb.document_count = doc_count
db.flush()
# 构建知识图谱节点和边
graph_data = _build_knowledge_graph(db, kb)
conv.knowledge_graph_base_id = kb.id
conv.knowledge_graph_count = 1
conv.updated_at = cst_now()
db.commit()
@@ -1285,6 +1314,8 @@ def convert_to_knowledge_graph(
"knowledge_base_id": kb.id,
"knowledge_base_name": kb.name,
"graph": graph_data,
"knowledge_graph_count": 1,
"already_exists": False,
},
"message": f"知识图谱构建完成",
}
@@ -1299,6 +1330,7 @@ def get_models(db: Session = Depends(get_db)):
result.append({
"id": m.id,
"name": m.name,
"display_name": getattr(m, "display_name", None) or m.name,
"provider_id": m.provider_id,
"provider_name": provider.name if provider else "",
"status": m.status,
File diff suppressed because it is too large. Load diff