chore: normalize line endings to LF via .gitattributes
Root-cause fix for mixed CRLF/LF in the repo (no .gitattributes previously). Adds '* text=auto eol=lf' and explicit binary rules so all future checkouts are LF. Renormalizes all tracked text files (no logical content change). Backup tags: image qihuaiflow:backup-lineend-20260725-121632, git backup-lineend-pre-20260725-121632.
This commit is contained in:
1 parent
2a7bb875f9
commit
771c8456b8
39 files changed
+34810
-34777
No files matched your search
@@ -1,319 +1,319 @@
|
||||
# Auto-extracted from chat.py during Phase 1 refactor (Strangler Fig).
|
||||
# Source of truth: scripts/phase1_extract.py. Do not hand-merge back.
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Response
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_, desc, asc, func
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
import uuid
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import re
|
||||
import json
|
||||
import asyncio
|
||||
import math
|
||||
import httpx
|
||||
import os
|
||||
import logging
|
||||
from ..database import get_db, SessionLocal
|
||||
from ..models import (
|
||||
|
||||
|
||||
|
||||
User, Conversation, Message, AIModel, ModelProvider, TokenUsageLog,
|
||||
|
||||
|
||||
|
||||
KnowledgeBase, KnowledgeDocument, KnowledgeDocumentChunk, EvolutionSkill,
|
||||
|
||||
|
||||
|
||||
EvolutionTrajectory, MarketApp, AppPurchase, AppInstallation,
|
||||
|
||||
|
||||
|
||||
MCPServer,
|
||||
|
||||
|
||||
|
||||
gen_uuid
|
||||
|
||||
|
||||
|
||||
)
|
||||
from ..auth import get_current_user
|
||||
from ..platform_knowledge import get_platform_knowledge
|
||||
from ..mcp_client import list_mcp_tools, call_mcp_tool
|
||||
from ..middleware.log_service import LogService
|
||||
from ..capability_registry import resolve_auto_model
|
||||
from app.api.chat_utils import (cst_now)
|
||||
|
||||
def _build_knowledge_graph(db: Session, kb: KnowledgeBase) -> dict:
|
||||
|
||||
|
||||
|
||||
"""从知识库文档构建知识图谱节点和边,返回 graph_data。"""
|
||||
|
||||
|
||||
|
||||
documents = db.query(KnowledgeDocument).filter(
|
||||
|
||||
|
||||
|
||||
and_(
|
||||
|
||||
|
||||
|
||||
KnowledgeDocument.knowledge_base_id == kb.id,
|
||||
|
||||
|
||||
|
||||
KnowledgeDocument.status == "completed",
|
||||
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
).all()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
graph_nodes = []
|
||||
|
||||
|
||||
|
||||
graph_edges = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
doc_entity_types = [
|
||||
|
||||
|
||||
|
||||
{"type": "concept", "label": "核心概念"},
|
||||
|
||||
|
||||
|
||||
{"type": "entity", "label": "关键实体"},
|
||||
|
||||
|
||||
|
||||
{"type": "attribute", "label": "属性特征"},
|
||||
|
||||
|
||||
|
||||
{"type": "relation", "label": "关联关系"},
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for idx, doc in enumerate(documents):
|
||||
|
||||
|
||||
|
||||
doc_node_id = f"doc-{doc.id[:8]}"
|
||||
|
||||
|
||||
|
||||
graph_nodes.append({
|
||||
|
||||
|
||||
|
||||
"id": doc_node_id, "label": doc.filename, "type": "document", "size": 18, "group": "document",
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
filename_base = doc.filename.rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
words = filename_base.replace("_", " ").replace("-", " ").split()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for wi, word in enumerate(words):
|
||||
|
||||
|
||||
|
||||
if len(word) >= 2:
|
||||
|
||||
|
||||
|
||||
entity_type = doc_entity_types[wi % len(doc_entity_types)]
|
||||
|
||||
|
||||
|
||||
node_id = f"ent-{doc.id[:8]}-{wi}"
|
||||
|
||||
|
||||
|
||||
graph_nodes.append({
|
||||
|
||||
|
||||
|
||||
"id": node_id, "label": word, "type": entity_type["type"],
|
||||
|
||||
|
||||
|
||||
"size": 10 + (wi % 8), "group": entity_type["type"],
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
graph_edges.append({
|
||||
|
||||
|
||||
|
||||
"source": doc_node_id, "target": node_id,
|
||||
|
||||
|
||||
|
||||
"label": entity_type["label"], "weight": 0.5 + (0.5 / (wi + 1)),
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for i in range(len(documents)):
|
||||
|
||||
|
||||
|
||||
for j in range(i + 1, len(documents)):
|
||||
|
||||
|
||||
|
||||
fi = documents[i].filename.lower().rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
fj = documents[j].filename.lower().rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
words_i = set(fi.replace("_", " ").replace("-", " ").split())
|
||||
|
||||
|
||||
|
||||
words_j = set(fj.replace("_", " ").replace("-", " ").split())
|
||||
|
||||
|
||||
|
||||
common = words_i & words_j
|
||||
|
||||
|
||||
|
||||
if common and len(common) > 0:
|
||||
|
||||
|
||||
|
||||
graph_edges.append({
|
||||
|
||||
|
||||
|
||||
"source": f"doc-{documents[i].id[:8]}",
|
||||
|
||||
|
||||
|
||||
"target": f"doc-{documents[j].id[:8]}",
|
||||
|
||||
|
||||
|
||||
"label": f"共有关键词: {', '.join(list(common)[:3])}",
|
||||
|
||||
|
||||
|
||||
"weight": min(0.9, 0.3 * len(common)),
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
graph_data = {
|
||||
|
||||
|
||||
|
||||
"nodes": graph_nodes,
|
||||
|
||||
|
||||
|
||||
"edges": graph_edges,
|
||||
|
||||
|
||||
|
||||
"stats": {
|
||||
|
||||
|
||||
|
||||
"total_nodes": len(graph_nodes), "total_edges": len(graph_edges),
|
||||
|
||||
|
||||
|
||||
"document_count": len(documents),
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
kb.knowledge_graph_count = len(graph_nodes)
|
||||
|
||||
|
||||
|
||||
kb.updated_at = cst_now()
|
||||
|
||||
|
||||
|
||||
return graph_data
|
||||
# Auto-extracted from chat.py during Phase 1 refactor (Strangler Fig).
|
||||
# Source of truth: scripts/phase1_extract.py. Do not hand-merge back.
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Response
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_, desc, asc, func
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
import uuid
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import re
|
||||
import json
|
||||
import asyncio
|
||||
import math
|
||||
import httpx
|
||||
import os
|
||||
import logging
|
||||
from ..database import get_db, SessionLocal
|
||||
from ..models import (
|
||||
|
||||
|
||||
|
||||
User, Conversation, Message, AIModel, ModelProvider, TokenUsageLog,
|
||||
|
||||
|
||||
|
||||
KnowledgeBase, KnowledgeDocument, KnowledgeDocumentChunk, EvolutionSkill,
|
||||
|
||||
|
||||
|
||||
EvolutionTrajectory, MarketApp, AppPurchase, AppInstallation,
|
||||
|
||||
|
||||
|
||||
MCPServer,
|
||||
|
||||
|
||||
|
||||
gen_uuid
|
||||
|
||||
|
||||
|
||||
)
|
||||
from ..auth import get_current_user
|
||||
from ..platform_knowledge import get_platform_knowledge
|
||||
from ..mcp_client import list_mcp_tools, call_mcp_tool
|
||||
from ..middleware.log_service import LogService
|
||||
from ..capability_registry import resolve_auto_model
|
||||
from app.api.chat_utils import (cst_now)
|
||||
|
||||
def _build_knowledge_graph(db: Session, kb: KnowledgeBase) -> dict:
|
||||
|
||||
|
||||
|
||||
"""从知识库文档构建知识图谱节点和边,返回 graph_data。"""
|
||||
|
||||
|
||||
|
||||
documents = db.query(KnowledgeDocument).filter(
|
||||
|
||||
|
||||
|
||||
and_(
|
||||
|
||||
|
||||
|
||||
KnowledgeDocument.knowledge_base_id == kb.id,
|
||||
|
||||
|
||||
|
||||
KnowledgeDocument.status == "completed",
|
||||
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
).all()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
graph_nodes = []
|
||||
|
||||
|
||||
|
||||
graph_edges = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
doc_entity_types = [
|
||||
|
||||
|
||||
|
||||
{"type": "concept", "label": "核心概念"},
|
||||
|
||||
|
||||
|
||||
{"type": "entity", "label": "关键实体"},
|
||||
|
||||
|
||||
|
||||
{"type": "attribute", "label": "属性特征"},
|
||||
|
||||
|
||||
|
||||
{"type": "relation", "label": "关联关系"},
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for idx, doc in enumerate(documents):
|
||||
|
||||
|
||||
|
||||
doc_node_id = f"doc-{doc.id[:8]}"
|
||||
|
||||
|
||||
|
||||
graph_nodes.append({
|
||||
|
||||
|
||||
|
||||
"id": doc_node_id, "label": doc.filename, "type": "document", "size": 18, "group": "document",
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
filename_base = doc.filename.rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
words = filename_base.replace("_", " ").replace("-", " ").split()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for wi, word in enumerate(words):
|
||||
|
||||
|
||||
|
||||
if len(word) >= 2:
|
||||
|
||||
|
||||
|
||||
entity_type = doc_entity_types[wi % len(doc_entity_types)]
|
||||
|
||||
|
||||
|
||||
node_id = f"ent-{doc.id[:8]}-{wi}"
|
||||
|
||||
|
||||
|
||||
graph_nodes.append({
|
||||
|
||||
|
||||
|
||||
"id": node_id, "label": word, "type": entity_type["type"],
|
||||
|
||||
|
||||
|
||||
"size": 10 + (wi % 8), "group": entity_type["type"],
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
graph_edges.append({
|
||||
|
||||
|
||||
|
||||
"source": doc_node_id, "target": node_id,
|
||||
|
||||
|
||||
|
||||
"label": entity_type["label"], "weight": 0.5 + (0.5 / (wi + 1)),
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for i in range(len(documents)):
|
||||
|
||||
|
||||
|
||||
for j in range(i + 1, len(documents)):
|
||||
|
||||
|
||||
|
||||
fi = documents[i].filename.lower().rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
fj = documents[j].filename.lower().rsplit(".", 1)[0]
|
||||
|
||||
|
||||
|
||||
words_i = set(fi.replace("_", " ").replace("-", " ").split())
|
||||
|
||||
|
||||
|
||||
words_j = set(fj.replace("_", " ").replace("-", " ").split())
|
||||
|
||||
|
||||
|
||||
common = words_i & words_j
|
||||
|
||||
|
||||
|
||||
if common and len(common) > 0:
|
||||
|
||||
|
||||
|
||||
graph_edges.append({
|
||||
|
||||
|
||||
|
||||
"source": f"doc-{documents[i].id[:8]}",
|
||||
|
||||
|
||||
|
||||
"target": f"doc-{documents[j].id[:8]}",
|
||||
|
||||
|
||||
|
||||
"label": f"共有关键词: {', '.join(list(common)[:3])}",
|
||||
|
||||
|
||||
|
||||
"weight": min(0.9, 0.3 * len(common)),
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
graph_data = {
|
||||
|
||||
|
||||
|
||||
"nodes": graph_nodes,
|
||||
|
||||
|
||||
|
||||
"edges": graph_edges,
|
||||
|
||||
|
||||
|
||||
"stats": {
|
||||
|
||||
|
||||
|
||||
"total_nodes": len(graph_nodes), "total_edges": len(graph_edges),
|
||||
|
||||
|
||||
|
||||
"document_count": len(documents),
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
kb.knowledge_graph_count = len(graph_nodes)
|
||||
|
||||
|
||||
|
||||
kb.updated_at = cst_now()
|
||||
|
||||
|
||||
|
||||
return graph_data
|
||||
Reference in new issue
Block a user