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

145 lines
5.5 KiB
Markdown
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.

# 第八阶段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 的 `ChatHistory``ChatMessageContent``KernelContent`、tool call object graph 或 provider 原始 response 直接作为 EF Core 持久化模型。原因:
- SK 的对象模型适合运行时编排,不适合作为长期数据库 schema。
- OpenAI-compatible provider 的消息格式并不完全等价DeepSeek 这类接口对 `role``content``tool_calls``tool_call_id` 的结构要求更严格。
- 如果把 SK metadata、内部 content item 或历史 tool 结构原样回放给 DeepSeek容易触发请求参数错误。
- 后续换 provider、增加 function call 或做消息压缩时,直接持久化 SK 对象会变成强耦合。
数据库只保存 provider-neutral 的规范化消息:
- `AiConversation`
- `TenantId`
- `TeacherUserId`
- `Title`
- `Scenario``teacher_chat`、后续可扩展。
- `ProviderCode`
- `Model`
- `Status`
- `Metadata`
- `AiConversationMessage`
- `TenantId`
- `ConversationId`
- `Sequence`
- `Role`:固定为 `system``user``assistant``tool`
- `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 call`role=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` 禁止出现 `secret``token``apiKey``key``privateKey` 等敏感字段。
- `Microsoft.SemanticKernel` NuGet 包只引用在 `Tiku.Infrastructure`
- `Tiku.Api``Tiku.Application``Tiku.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 配置。