请实现一个完整的AI对话模块,集成阿里云百炼平台(DashScope),支持流式/非流式对话、会话管理、消息记录和费用计算功能。
创建 app/services/dashscope_client.py:
创建 app/services/llm_service.py:
incremental_output=True,每次返回增量内容full_content += chunk.contentdata: [DONE]\n\n创建 app/models/conversation.py:
AIConversation表(ai_conversation):
AIMessage表(ai_message):
创建 app/services/conversation_service.py:
创建 app/services/message_service.py:
创建 app/services/billing_calculator.py:
创建 app/routers/llm_router.py:
POST /api/llm/chat
- 统一对话端点,支持流式和非流式
- 需要用户认证
- 请求体:model, messages, stream, temperature, top_p, max_tokens, conversation_id
- 流式返回:StreamingResponse (text/event-stream)
- 非流式返回:ApiResponse包装
GET /api/llm/models
- 获取所有LLM模型列表(category=0)
创建 app/routers/conversation_router.py:
POST /api/conversations - 创建会话
GET /api/conversations - 获取用户会话列表
GET /api/conversations/{id} - 获取会话详情(含消息)
PUT /api/conversations/{id} - 更新会话标题
DELETE /api/conversations/{id} - 删除会话
GET /api/conversations/{id}/messages - 获取会话消息
创建 app/schemas/llm_schema.py:
ChatMessage: role(Literal["system","user","assistant"]), content
ChatRequest: model, messages, stream, temperature, top_p, max_tokens, conversation_id
UsageInfo: input_tokens, output_tokens, total_tokens
ChatResponse: content, finish_reason, usage
StreamChunk: content, finish_reason, usage(Optional)
创建 app/schemas/conversation_schema.py:
ConversationCreate: title
ConversationUpdate: title
ConversationResponse: id, user_id, title, tokens统计, bill, 时间戳
MessageResponse: id, conversation_id, role, content, tokens统计, model_id, model_name, created_at
ConversationDetailResponse: 会话信息 + messages列表
创建迁移文件:
011_create_ai_conversation_table.sql:
012_create_ai_message_table.sql:
full_content = ""
for response in self.client.call_stream(...):
if choice.message.content:
full_content += choice.message.content # 累加,不是覆盖
yield f"data: {chunk.model_dump_json()}\n\n"
# 流结束后保存full_content到数据库
data: {"content":"你好","finish_reason":null}\n\n
data: {"content":"!","finish_reason":"stop","usage":{...}}\n\n
data: [DONE]\n\n
在 main.py 中注册:
from app.routers import llm_router, conversation_router
app.include_router(llm_router.router)
app.include_router(conversation_router.router)