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:
1 parent
7c71d193fc
commit
7b7871a14d
5 files changed
+1044
-955
No files matched your search
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user