Files
wecom_it_smart_desk/backend/app/models/knowledge_suggestion.py
T
Simon ead5f83bee feat(backend): knowledge iteration + vision + neo4j + response contract source
dependencies.py 拆分为 dependencies/ 包; 新增 vision/ragflow_ingestion/neo4j 客户端与 h5_ai_task; alembic 045 图置信度迁移; 响应契约统一收尾。
2026-07-09 11:47:16 +08:00

260 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 企微IT智能服务台 — 知识库优化建议模型
# =============================================================================
# 说明:对应数据库 knowledge_suggestions 表
# 存储AI分析生成的优化建议,用于知识库迭代
# 分析维度:错误标注高频问题、未命中知识库的会话、AI不确定回复
# =============================================================================
import uuid
from datetime import datetime
from typing import Any, Dict, List, Optional
from sqlalchemy import Boolean, DateTime, Float, Index, JSON, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class KnowledgeSuggestion(Base):
"""知识库优化建议模型 — 对应 knowledge_suggestions 表。
存储AI自动分析生成的优化建议,用于知识库持续迭代。
Attributes:
id: 建议IDUUID
suggestion_type: 建议类型(new_faq=新增FAQ/update=更新/outdated=标记过时)
status: 状态(pending=待审核/approved=已通过/rejected=已拒绝/applied=已应用)
title: 建议标题(新增/更新的FAQ标题)
content: 建议内容(答案内容)
category: 分类
tags: 标签列表(JSON数组)
source_type: 分析来源(annotation=标注数据/conversation=会话数据/ai_uncertain=AI不确定)
source_data: 来源数据(JSON,存储相关会话ID或标注ID列表)
reason: 生成理由(AI分析的理由)
reject_reason: 拒绝理由(审核拒绝时填写)
reviewer_id: 审核人ID
reviewed_at: 审核时间
created_at: 创建时间
updated_at: 更新时间
"""
# 表名
__tablename__ = "knowledge_suggestions"
# --------------------------------------------------------------------------
# 字段定义
# --------------------------------------------------------------------------
# 主键
id: Mapped[str] = mapped_column(
String(36),
primary_key=True,
default=lambda: str(uuid.uuid4()),
)
# 建议类型
suggestion_type: Mapped[str] = mapped_column(
String(20),
nullable=False,
default="new_faq",
comment="new_faq=新增FAQ/update=更新/outdated=标记过时",
)
# 状态
status: Mapped[str] = mapped_column(
String(20),
nullable=False,
default="pending",
index=True,
comment="pending=待审核/approved=已通过/rejected=已拒绝/applied=已应用",
)
# 建议标题
title: Mapped[str] = mapped_column(
String(256),
nullable=False,
comment="新增/更新的FAQ标题",
)
# 建议内容
content: Mapped[str] = mapped_column(
Text,
nullable=False,
comment="答案内容",
)
# 分类
category: Mapped[str] = mapped_column(
String(64),
nullable=False,
default="其他",
comment="分类:硬件/软件/网络/安全/账号/其他",
)
# 标签列表
tags: Mapped[List[str]] = mapped_column(
JSON,
nullable=False,
default=list,
comment="标签列表",
)
# 分析来源
source_type: Mapped[str] = mapped_column(
String(30),
nullable=False,
comment="annotation=标注数据/conversation=会话数据/ai_uncertain=AI不确定",
)
# 来源数据(JSON
source_data: Mapped[Optional[List[str]]] = mapped_column(
JSON,
nullable=True,
comment="相关会话ID或标注ID列表",
)
# --------------------------------------------------------------------------
# Tier0 扩展字段 — 图结构 + 置信度 + 受众 + 状态(D1/D3/D7/D8
# --------------------------------------------------------------------------
# AI 生成置信度(0.0-1.0D3 门控阈值 0.7
confidence: Mapped[Optional[float]] = mapped_column(
Float,
nullable=True,
comment="AI 生成置信度(0.0-1.0",
)
# 受众类型(D8employee_quick_reply / engineer_workguide
audience: Mapped[Optional[str]] = mapped_column(
String(30),
nullable=True,
comment="受众类型:employee_quick_reply / engineer_workguide",
)
# 图结构字段 — 问题名称(对应 Neo4j Issue.name
issue: Mapped[Optional[str]] = mapped_column(
String(256),
nullable=True,
comment="图节点:问题名称",
)
# 图结构字段 — 动作名称(对应 Neo4j Action.name
action: Mapped[Optional[str]] = mapped_column(
String(256),
nullable=True,
comment="图节点:动作名称",
)
# 图关系类型(LEADS_TO / RELATES_TO / CAN_JUMP_TO
relation_type: Mapped[Optional[str]] = mapped_column(
String(30),
nullable=True,
comment="图关系类型",
)
# 父 Issue 名称(用于构建 Issue→Issue 关系)
parent_issue: Mapped[Optional[str]] = mapped_column(
String(256),
nullable=True,
comment="父 Issue 名称",
)
# 图结构扩展元数据(JSON,存放额外的图属性)
graph_meta: Mapped[Optional[Dict[str, Any]]] = mapped_column(
JSON,
nullable=True,
comment="图结构扩展元数据",
)
# 图同步状态(pending / synced / failed
graph_sync_status: Mapped[str] = mapped_column(
String(20),
nullable=False,
default="pending",
comment="图同步状态:pending / synced / failed",
)
# AI 生成失败标记(Dify 不可用或置信度不足时置 True)
source_failed: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=False,
comment="AI 生成失败标记",
)
# 入队列时间
queued_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="入独立队列时间",
)
# 应用到 KB 的时间
applied_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="应用到 KB 的时间",
)
# 生成理由
reason: Mapped[Optional[str]] = mapped_column(
Text,
nullable=True,
comment="AI分析的理由",
)
# 拒绝理由
reject_reason: Mapped[Optional[str]] = mapped_column(
Text,
nullable=True,
comment="审核拒绝时填写",
)
# 审核人ID
reviewer_id: Mapped[Optional[str]] = mapped_column(
String(36),
nullable=True,
comment="审核人ID",
)
# 审核时间
reviewed_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="审核时间",
)
# 创建时间
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
comment="创建时间",
)
# 更新时间
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=datetime.now,
onupdate=datetime.now,
comment="更新时间",
)
# --------------------------------------------------------------------------
# 索引定义
# --------------------------------------------------------------------------
__table_args__ = (
Index("idx_suggestion_status", "status"),
Index("idx_suggestion_type", "suggestion_type"),
Index("idx_suggestion_created", "created_at"),
Index("idx_suggestion_audience", "audience"),
Index("idx_suggestion_confidence", "confidence"),
Index("idx_suggestion_graph_sync", "graph_sync_status"),
)
def __repr__(self) -> str:
"""建议对象的字符串表示。"""
return f"<KnowledgeSuggestion(id={self.id}, type={self.suggestion_type}, status={self.status})>"