Files
tiku-backend.net/docs/migration/phase-8-ai-foundation.md

5.5 KiB
Raw Blame History

第八阶段AI 底座与教师端对话

第八阶段从“只预留 AI”进入 AI 底座建设。AI 当前只面向租户教师和后台运营,不开放给学生端。

当前 AI 使用场景

1. 租户教师 AI 对话

第一批先做基础对话能力:

  • 教师在租户后台发起对话。
  • AI 根据当前租户配置调用模型。
  • 对话历史按租户和教师隔离保存。
  • 响应不暴露模型 API Key、Provider 原始响应密钥、内部租户 ID 或对象存储细节。
  • 后续可追加 function calling用于读取或操作受控业务能力。

预留 function call 的原则:

  • Controller 不直接暴露任意 tool/function 名称给客户端调用。
  • Application 层定义可用业务函数目录,例如题目检索、题目草稿生成、班级学习概览、学生跟进建议。
  • Infrastructure 用 Semantic Kernel 把受审计的业务函数注册为 plugin。
  • 每个 function call 都必须记录租户、教师、会话、函数名、输入摘要、结果状态和耗时。
  • 有写操作的 function 必须复用现有 RBAC、DataScope、Tenant Scope 和 AuditLog不允许 AI 绕过后台权限。

对话存储模型

不要把 Semantic Kernel 的 ChatHistoryChatMessageContentKernelContent、tool call object graph 或 provider 原始 response 直接作为 EF Core 持久化模型。原因:

  • SK 的对象模型适合运行时编排,不适合作为长期数据库 schema。
  • OpenAI-compatible provider 的消息格式并不完全等价DeepSeek 这类接口对 rolecontenttool_callstool_call_id 的结构要求更严格。
  • 如果把 SK metadata、内部 content item 或历史 tool 结构原样回放给 DeepSeek容易触发请求参数错误。
  • 后续换 provider、增加 function call 或做消息压缩时,直接持久化 SK 对象会变成强耦合。

数据库只保存 provider-neutral 的规范化消息:

  • AiConversation
    • TenantId
    • TeacherUserId
    • Title
    • Scenarioteacher_chat、后续可扩展。
    • ProviderCode
    • Model
    • Status
    • Metadata
  • AiConversationMessage
    • TenantId
    • ConversationId
    • Sequence
    • Role:固定为 systemuserassistanttool
    • ContentText
    • ToolCallId
    • ToolName
    • ToolArguments
    • ToolResultSummary
    • ProviderMessageId
    • TokenInput
    • TokenOutput
    • Metadata
  • AiToolCallLog
    • TenantId
    • ConversationId
    • MessageId
    • ToolCallId
    • ToolName
    • InputSummary
    • ResultStatus
    • DurationMs
    • ErrorCode

运行时转换规则:

  1. Application 层读取规范化消息,不产生 SK 类型。
  2. Infrastructure adapter 把规范化消息转换成 Semantic Kernel ChatHistory
  3. DeepSeek/OpenAI-compatible adapter 只发送 provider 接受的字段:
    • 普通消息:role + content
    • assistant tool callrole=assistant + tool_calls
    • tool 结果:role=tool + tool_call_id + content
  4. Provider 原始响应只保存必要摘要和可审计 ID不作为下一轮请求的直接输入。
  5. 任何无法被目标 provider 表达的 SK metadata 都必须丢弃或写入内部 Metadata,不得回放给模型 API。

2. AI 审核题目反馈

这个场景保持简单,不做复杂扩展:

  • 输入:题目反馈内容、题目基本信息、反馈类型、提交用户上下文摘要。
  • 输出:审核建议、风险等级、归类标签、是否建议人工复核。
  • 不做 function calling。
  • 不直接修改题目、反馈状态或用户数据。
  • 只生成建议结果,最终状态变更仍由教师或运营人员确认。

Provider 与密钥边界

  • AI Provider 使用 TenantExternalProvider(capability=ai)
  • 租户自己的模型 API Key 存入 TenantSecret,通过 SecretRef 关联。
  • ConfigPublic 只允许保存公开配置,例如 provider、model、endpoint、deployment、temperature 默认值、max token 限制。
  • ConfigPublic 禁止出现 secrettokenapiKeykeyprivateKey 等敏感字段。
  • Microsoft.SemanticKernel NuGet 包只引用在 Tiku.Infrastructure
  • Tiku.ApiTiku.ApplicationTiku.Domain 不直接引用 Semantic Kernel namespace。

建议模块边界

Application 层后续只放业务抽象:

  • IAiConversationService
  • IAiFeedbackReviewService
  • IAiKernelFactory
  • IAiProviderConfigService

Infrastructure 层负责:

  • 根据当前租户 Provider 配置和 TenantSecret 创建 Kernel。
  • 注册受审计 plugin。
  • 调用 chat completion。
  • 处理 provider 错误、超时、重试和调用日志。

Domain 层可增加持久化模型:

  • AiConversation
  • AiConversationMessage
  • AiToolCallLog
  • AiFeedbackReview

第一批实施顺序

  1. 增加 AI Provider capability、Semantic Kernel 包和架构测试边界。
  2. 增加 AI 配置服务测试:租户 A/B 不能互读模型配置和密钥。
  3. 增加教师对话数据模型和最小 API
    • POST /api/tenant-admin/ai/conversations
    • GET /api/tenant-admin/ai/conversations
    • GET /api/tenant-admin/ai/conversations/{conversationId}
    • POST /api/tenant-admin/ai/conversations/{conversationId}/messages
  4. 增加 fake AI provider先跑通对话和日志不接真实模型。
  5. 增加题目反馈审核最小 API
    • POST /api/tenant-admin/ai/question-feedback/review
  6. 最后再接真实模型 Provider。

暂不做

  • 学生端 AI。
  • 复杂 RAG。
  • 自动改题、自动发布题目。
  • 自动处理反馈状态。
  • 让客户端指定任意 function call。
  • 生产环境使用明文 API Key 配置。