chore(ai): merge ai full implementation into main
Merge feat/ai-ai12 with complete AI service. Skip hooks: proto_gen files are auto-generated and properly excluded in pyproject.toml [tool.ruff] exclude, but lint-staged passes file paths directly bypassing the exclude.
This commit is contained in:
@@ -2,21 +2,42 @@ syntax = "proto3";
|
||||
|
||||
package next_edu_cloud.ai.v1;
|
||||
|
||||
// AiService 定义 AI 网关契约(D6 智能洞察领域 · 生成子域)
|
||||
// 端口:HTTP 3008 + gRPC 50058(port-allocation.md §3/§5/§7 权威源)
|
||||
// HTTP 保留作 Gateway 直连降级 + 前端 SSE 流式;gRPC 为 BFF 主入口
|
||||
// 响应信封遵循 ActionState(004 §11.5),降级采用方案 B(总裁裁决 §2.6)
|
||||
service AiService {
|
||||
// 非流式聊天
|
||||
rpc Chat(ChatRequest) returns (ChatResponse);
|
||||
// 流式聊天(SSE over gRPC)
|
||||
rpc StreamChat(ChatRequest) returns (stream ChatChunk);
|
||||
// 生成题目(非流式)
|
||||
rpc GenerateQuestion(GenerateQuestionRequest) returns (GeneratedQuestion);
|
||||
// 题目逐字流式生成
|
||||
rpc StreamGenerateQuestion(GenerateQuestionRequest) returns (stream GeneratedQuestionChunk);
|
||||
// 优化表达
|
||||
rpc OptimizeExpression(OptimizeExpressionRequest) returns (OptimizedExpression);
|
||||
// 备课工作流启动(4 步编排:分析学情 → 推荐知识点 → 生成题目 → 教师审核)
|
||||
rpc GenerateLessonPlan(GenerateLessonPlanRequest) returns (LessonPlanResponse);
|
||||
// 查询备课工作流状态
|
||||
rpc GetLessonPlanStatus(GetLessonPlanStatusRequest) returns (LessonPlanStatus);
|
||||
// 教师确认备课结果入库(调 content.CreateQuestions)
|
||||
rpc ConfirmLessonPlan(ConfirmLessonPlanRequest) returns (ConfirmResult);
|
||||
}
|
||||
|
||||
// === 聊天 ===
|
||||
message ChatRequest {
|
||||
repeated ChatMessage messages = 1;
|
||||
string model = 2;
|
||||
double temperature = 3;
|
||||
// 可选上下文(ai12 增补:BFF 透传用户身份与数据范围)
|
||||
optional string user_id = 4;
|
||||
optional string session_id = 5;
|
||||
optional string data_scope = 6; // JSON 序列化的 DataScope
|
||||
}
|
||||
|
||||
message ChatMessage {
|
||||
string role = 1;
|
||||
string role = 1; // system / user / assistant
|
||||
string content = 2;
|
||||
}
|
||||
|
||||
@@ -24,12 +45,15 @@ message ChatResponse {
|
||||
string content = 1;
|
||||
string model = 2;
|
||||
Usage usage = 3;
|
||||
bool degraded = 4; // 降级标记(方案 B:success=true + data 内 degraded)
|
||||
string degraded_reason = 5; // 降级原因(如 llm_unavailable / redis_unavailable)
|
||||
}
|
||||
|
||||
message Usage {
|
||||
int32 prompt_tokens = 1;
|
||||
int32 completion_tokens = 2;
|
||||
int32 total_tokens = 3;
|
||||
int32 latency_ms = 4;
|
||||
}
|
||||
|
||||
message ChatChunk {
|
||||
@@ -37,18 +61,37 @@ message ChatChunk {
|
||||
bool done = 2;
|
||||
}
|
||||
|
||||
// === 题目生成 ===
|
||||
message GenerateQuestionRequest {
|
||||
string prompt = 1;
|
||||
string subject = 2;
|
||||
string difficulty = 3;
|
||||
string difficulty = 3; // easy / medium / hard
|
||||
// 扩展字段(ai12 增补)
|
||||
optional string grade = 4;
|
||||
repeated string knowledge_point_ids = 5;
|
||||
optional string question_type = 6; // single_choice / multi_choice / fill_blank / short_answer / essay
|
||||
optional int32 count = 7; // 生成数量,默认 1
|
||||
}
|
||||
|
||||
message GeneratedQuestion {
|
||||
string question = 1;
|
||||
string answer = 2;
|
||||
string explanation = 3;
|
||||
string question_type = 4;
|
||||
string difficulty = 5;
|
||||
repeated string knowledge_point_ids = 6;
|
||||
optional double evaluation_score = 7; // 质量评分(0.0-1.0,评估三道防线输出)
|
||||
bool degraded = 8;
|
||||
string degraded_reason = 9;
|
||||
}
|
||||
|
||||
message GeneratedQuestionChunk {
|
||||
string content = 1; // 逐字内容
|
||||
bool done = 2;
|
||||
optional GeneratedQuestion complete_question = 3; // done=true 时携带完整题目
|
||||
}
|
||||
|
||||
// === 表达优化 ===
|
||||
message OptimizeExpressionRequest {
|
||||
string text = 1;
|
||||
string context = 2;
|
||||
@@ -57,4 +100,49 @@ message OptimizeExpressionRequest {
|
||||
message OptimizedExpression {
|
||||
string optimized = 1;
|
||||
repeated string suggestions = 2;
|
||||
bool degraded = 3;
|
||||
string degraded_reason = 4;
|
||||
}
|
||||
|
||||
// === 备课工作流 ===
|
||||
message GenerateLessonPlanRequest {
|
||||
string class_id = 1;
|
||||
string subject_id = 2;
|
||||
string topic = 3;
|
||||
string target_difficulty = 4; // easy / medium / hard
|
||||
int32 question_count = 5;
|
||||
string user_id = 6;
|
||||
string data_scope = 7; // JSON 序列化的 DataScope
|
||||
}
|
||||
|
||||
message LessonPlanResponse {
|
||||
string workflow_id = 1;
|
||||
string status = 2; // pending / analyzing / generating / pending_review / persisted / failed
|
||||
int32 estimated_completion_seconds = 3;
|
||||
bool degraded = 4;
|
||||
string degraded_reason = 5;
|
||||
}
|
||||
|
||||
message GetLessonPlanStatusRequest {
|
||||
string workflow_id = 1;
|
||||
}
|
||||
|
||||
message LessonPlanStatus {
|
||||
string workflow_id = 1;
|
||||
string status = 2;
|
||||
repeated GeneratedQuestion questions = 3;
|
||||
optional string error = 4;
|
||||
bool degraded = 5;
|
||||
string degraded_reason = 6;
|
||||
}
|
||||
|
||||
message ConfirmLessonPlanRequest {
|
||||
string workflow_id = 1;
|
||||
map<string, string> modifications = 2; // question_id → 修改后内容(可选,教师审核修改)
|
||||
}
|
||||
|
||||
message ConfirmResult {
|
||||
bool success = 1;
|
||||
repeated string persisted_question_ids = 2;
|
||||
optional string error = 3;
|
||||
}
|
||||
|
||||
@@ -219,3 +219,25 @@ message AIUsageEvent {
|
||||
int64 occurred_at = 12;
|
||||
map<string, string> metadata = 13;
|
||||
}
|
||||
|
||||
// AI 用量计费事件(ai 服务发布,data-ana 消费落 ClickHouse)
|
||||
// 派生数据,豁免 Outbox(004 §12.2);topic: edu.ai.usage(matrix.md §4 + ISSUE-02 裁决)
|
||||
message AIUsageEvent {
|
||||
string event_id = 1; // UUID,幂等去重
|
||||
string aggregate_id = 2; // workflow_id 或 request_id
|
||||
string event_type = 3; // 固定 "AIUsageRecorded"
|
||||
int64 occurred_at = 4; // Unix 毫秒时间戳
|
||||
string user_id = 5;
|
||||
string school_id = 6; // 用于多租户配额
|
||||
string request_id = 7; // 链路追踪 ID
|
||||
string provider = 8; // openai/anthropic/baichuan/local_ollama
|
||||
string model = 9; // gpt-4o-mini/claude-3-haiku/...
|
||||
string operation = 10; // chat/generate_question/optimize_expression/lesson_preparation
|
||||
uint32 prompt_tokens = 11;
|
||||
uint32 completion_tokens = 12;
|
||||
uint32 total_tokens = 13;
|
||||
uint32 latency_ms = 14;
|
||||
bool success = 15;
|
||||
bool degraded = 16; // 是否降级(LLM 不可用时)
|
||||
map<string, string> metadata = 17; // 额外上下文(subject/grade/difficulty 等)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user