Files
aiagent/backend/app/models/knowledge_entry.py
renjianbo 876789fac1 feat: multi-tenant workspace isolation, RBAC, sidebar nav, billing, and Android enhancements
- Backend: workspace_id isolation for 14 model tables + safe migration/backfill
- Backend: RBAC system with 4 roles and 23 permissions, seeded on startup
- Backend: workspace admin endpoints (list/manage all workspaces)
- Backend: admin user management API (CRUD, reset password)
- Backend: billing API with subscription plans, usage tracking, rate limiting
- Backend: fix system_logs.py UNION query and wrong column references
- Backend: WebSocket JWT auth and workspace enforcement
- Frontend: sidebar navigation replacing top dropdown menu
- Frontend: user management page (Users.vue) for admins
- Frontend: enhanced Workspaces.vue with admin table view
- Frontend: workspace RBAC computed properties in user store
- Android: agent marketplace, billing/subscription UI, onboarding wizard
- Android: phone login, analytics tracker, crash handler, network diagnostics
- Android: splash screen, encrypted token storage, app update enhancements
- Docs: multi-tenant RBAC guide with 8 sections and role-permission matrix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-04 01:00:22 +08:00

72 lines
3.2 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.
"""
知识条目模型 — Agent 执行经验的结构化沉淀
"""
import uuid
from datetime import datetime
from sqlalchemy import Column, String, Text, Integer, DateTime, Boolean, JSON, Float, Index, ForeignKey
from sqlalchemy.dialects.mysql import CHAR
from app.core.database import Base
class KnowledgeEntry(Base):
"""从 Agent 执行日志中提取的可复用知识条目"""
__tablename__ = "knowledge_entries"
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
agent_id = Column(String(36), nullable=True, index=True, comment="所属 Agent IDNULL=全Agent共享")
workspace_id = Column(CHAR(36), ForeignKey("workspaces.id"), nullable=True, index=True, comment="工作区ID")
title = Column(String(500), nullable=False, comment="知识标题(一句话概括)")
category = Column(String(30), nullable=False, index=True,
comment="类别: bug_fix/best_practice/workaround/optimization/insight")
tags = Column(JSON, nullable=True, comment="标签列表: ['mysql','deadlock','retry']")
# 知识内容
situation = Column(Text, nullable=True, comment="适用场景")
solution = Column(Text, nullable=True, comment="解决方案")
caveats = Column(Text, nullable=True, comment="注意事项/踩坑记录")
# 来源追溯
source_execution_ids = Column(JSON, nullable=True, comment="原始执行日志ID列表")
source_agent_name = Column(String(200), nullable=True, comment="来源 Agent 名称")
source_model = Column(String(100), nullable=True, comment="来源模型")
# RAG 检索
embedding_text = Column(Text, nullable=True, comment="用于生成 embedding 的合并文本")
embedding = Column(Text, nullable=True, comment="JSON 序列化的 embedding 向量")
# 效果度量
retrieval_count = Column(Integer, default=0, comment="被检索次数")
success_rate = Column(Float, nullable=True, comment="应用成功率")
# 提取信息
extracted_by = Column(String(100), nullable=True, comment="提取方式: llm_auto/manual/reviewed")
confidence = Column(Float, default=0.5, comment="提取置信度(0-1)")
is_active = Column(Boolean, default=True, comment="是否启用")
created_at = Column(DateTime, default=datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")
__table_args__ = (
Index("ix_knowledge_entries_active", "is_active"),
)
def __repr__(self):
return f"<KnowledgeEntry(id={self.id}, title={self.title}, category={self.category})>"
def to_dict(self) -> dict:
return {
"id": self.id,
"agent_id": self.agent_id,
"workspace_id": self.workspace_id,
"title": self.title,
"category": self.category,
"tags": self.tags or [],
"situation": self.situation,
"solution": self.solution,
"caveats": self.caveats,
"source_agent_name": self.source_agent_name,
"retrieval_count": self.retrieval_count,
"confidence": self.confidence,
"created_at": self.created_at.isoformat() if self.created_at else None,
}