跳到主要内容

版本 0.10 API 接口设计

生成时间:2026-01-09 18:53:39
最后更新:2026-01-13 (WebSocket 实时对话协议)

YOLOX 项目 API 设计方案 (v0.10)

本方案基于 React Native 前端、Golang (Eino) 后端、PostgreSQL 关系数据库及 Milvus 向量数据库构建,旨在实现用户冷启动、动态 Prompt 对话及 Memory 管理核心逻辑。

API 分类说明

类型路径前缀说明
对外 API/api/v1/*Mobile App 调用,由 Backend 提供
内部 API/internal/v1/*Backend ↔ RAG 服务间调用

1. 认证与用户模块

1.1 发送验证码

  • 路径: /api/v1/auth/send-code
  • 方法: POST
  • 描述: 向指定手机号发送登录/注册验证码(6位数字,有效期5-10分钟)。
  • 请求体:
{
"phone_number": "+8613812345678"
}
  • 响应体:
{
"status": "success",
"message": "验证码已发送",
"expires_in": 600
}
  • 错误响应:
    • 400: 手机号格式错误
    • 429: 发送频率过高(如1分钟内重复发送)

1.2 验证码登录/注册

  • 路径: /api/v1/auth/login
  • 方法: POST
  • 描述: 使用手机号和验证码进行登录(新用户自动注册)。需要先验证邀请码(如果社区处于邀请制阶段)。
  • 请求体:
{
"phone_number": "+8613812345678",
"code": "123456",
"invitation_code": "INVITE20260109ABC" // 可选,邀请制阶段必填
}
  • 响应体:
{
"status": "success",
"user_id": "uuid-xxx",
"token": "jwt-token-xxx",
"is_new_user": true,
"is_onboarded": false
}
  • 错误响应:
    • 400: 验证码错误或已过期
    • 403: 邀请码无效、已使用或已过期
    • 404: 手机号未注册(如果仅支持登录,不支持注册)

1.3 验证邀请码(可选独立接口)

  • 路径: /api/v1/auth/verify-invitation
  • 方法: POST
  • 描述: 在注册前验证邀请码是否有效(可选,也可在登录接口中一并验证)。
  • 请求体:
{
"invitation_code": "INVITE20260109ABC"
}
  • 响应体:
{
"status": "valid",
"code": "INVITE20260109ABC",
"expires_at": "2026-02-09T00:00:00Z"
}
  • 错误响应:
    • 400: 邀请码格式错误
    • 403: 邀请码已使用或已过期
    • 404: 邀请码不存在

1.4 用户冷启动提交

  • 路径: /api/v1/user/onboarding
  • 方法: POST
  • 描述: 提交新用户问卷结果,初始化用户画像并触发首次话题推荐。
  • 请求体:
{
"answers": [
{"question_id": "q1", "selected_options": ["opt_a"]},
{"question_id": "q2", "selected_options": ["opt_b", "opt_c"]}
],
"channel": "xiaohongshu"
}
  • 响应体:
{
"status": "success",
"recommended_topics": [
{
"topic_id": "t_001",
"title": "分手后的深夜难熬时刻",
"cover_url": "https://r2.yolox.ai/assets/t1.png",
"level": "banner",
"button_text": "开始倾诉"
}
]
}

2. 话题与 Feed 模块

2.1 获取话题 Feed

  • 路径: /api/v1/topics/feed
  • 方法: GET
  • 描述: 基于用户 Memory 和配置获取个性化话题列表。
  • 请求参数: page, page_size
  • 响应体:
{
"items": [
{
"topic_id": "t_002",
"title": "职场倦怠:我在逃避什么?",
"cover_url": "https://r2.yolox.ai/assets/t2.png",
"level": "normal",
"reason": "基于你最近提到的职业压力"
}
],
"next_cursor": "..."
}

3. 对话 (Jot) 模块

技术选型:对话模块采用 WebSocket 实现全双工实时通信,支持文本消息、流式 AI 回复、状态推送,并为后续双工语音通话预留扩展能力。

3.1 创建/进入会话 (HTTP)

  • 路径: /api/v1/chat/session
  • 方法: POST
  • 描述: 根据话题 ID 初始化对话,获取 session_id 和欢迎语。
  • 请求体:
{
"topic_id": "t_001",
"entry_point": "homepage_long_press"
}
  • 响应体:
{
"session_id": "sess_9988",
"welcome_message": "看到你最近在经历这段艰难的时期,今晚感觉还好吗?",
"system_status": "ready",
"ws_url": "wss://api.yolox.ai/ws/chat?session_id=sess_9988"
}

3.2 WebSocket 连接

  • 路径: wss://api.yolox.ai/ws/chat
  • 描述: 对话页面的实时通信通道,支持消息收发、状态推送、流式输出。

3.2.1 连接建立

GET /ws/chat?session_id=sess_9988&token=jwt-token-xxx
Upgrade: websocket
Connection: Upgrade

3.2.2 连接生命周期

事件处理方式
进入对话页建立 WebSocket 连接
对话进行中保持连接,30s 心跳保活
切换到其他页面断开连接
App 切后台保持连接 60s 后超时断开
网络中断自动重连 + 消息恢复

3.3 WebSocket 消息协议

3.3.1 通用消息结构

interface WSMessage {
type: MessageType;
payload: object;
seq: number; // 消息序号,用于可靠性和去重
timestamp: number; // Unix 毫秒时间戳
ack_seq?: number; // 确认的消息序号(可选)
}

type MessageType =
// 客户端消息
| 'user_message' // 用户发送消息
| 'audio_chunk' // 语音流数据(预留)
| 'control' // 控制命令(心跳、模式切换等)
| 'ack' // 确认收到
// 服务端消息
| 'ai_stream' // AI 流式回复
| 'ai_complete' // AI 回复完成
| 'status_update' // 状态更新
| 'error'; // 错误信息

3.3.2 内容类型定义

type ContentType = 
| 'text' // 纯文本
| 'markdown' // Markdown 格式
| 'audio' // 音频(预留,用于双工语音)
| 'image' // 图片
| 'artifact' // 结构化内容(Summary、Insight)
| 'command'; // 指令/操作

3.3.3 AI 状态定义

enum AIStatus {
READY = 'ready', // 就绪,等待用户输入
THINKING = 'thinking', // AI 思考中
LOADING_MEMORY = 'loading_memory', // 加载用户记忆
SEARCHING = 'searching', // 检索知识库
STREAMING = 'streaming', // 流式输出中
SPEAKING = 'speaking', // AI 语音输出中(预留)
ERROR = 'error' // 错误状态
}

3.4 客户端消息详细定义

3.4.1 用户发送消息

{
"type": "user_message",
"payload": {
"content_type": "text",
"content": "我觉得特别孤独,尤其是关灯后。",
"input_source": "voice",
"metadata": {
"asr_duration_ms": 2500,
"asr_confidence": 0.95
}
},
"seq": 1001,
"timestamp": 1704067200000
}
字段类型必填说明
content_typestring内容类型:text, markdown
contentstring消息内容
input_sourcestring输入来源:voice, keyboard
metadataobject附加信息(ASR 时长、置信度等)

3.4.2 控制命令

心跳 Ping:

{
"type": "control",
"payload": {
"action": "ping"
},
"seq": 1002,
"timestamp": 1704067230000
}

停止生成:

{
"type": "control",
"payload": {
"action": "stop_generation"
},
"seq": 1003,
"timestamp": 1704067235000
}

控制命令类型:

action说明
ping心跳检测
stop_generation停止 AI 生成
regenerate重新生成上一条回复

3.5 服务端消息详细定义

3.5.1 状态更新

{
"type": "status_update",
"payload": {
"status": "loading_memory",
"message": "正在回忆我们之前聊过的..."
},
"seq": 2001,
"timestamp": 1704067200100
}

3.5.2 AI 流式回复

{
"type": "ai_stream",
"payload": {
"message_id": "msg_001",
"content_type": "markdown",
"delta": "我能理解",
"accumulated_length": 12
},
"seq": 2002,
"timestamp": 1704067200200
}
字段类型说明
message_idstring消息唯一标识
content_typestring内容类型
deltastring本次增量内容
accumulated_lengthnumber累计内容长度

3.5.3 AI 回复完成

{
"type": "ai_complete",
"payload": {
"message_id": "msg_001",
"content_type": "markdown",
"full_content": "我能理解这种深夜的孤独感...",
"token_usage": {
"prompt_tokens": 1200,
"completion_tokens": 150
},
"metadata": {
"model": "gpt-4",
"latency_ms": 2500
}
},
"seq": 2020,
"timestamp": 1704067202500
}

3.5.4 Artifact 输出(Summary/Insight)

{
"type": "ai_stream",
"payload": {
"message_id": "msg_002",
"content_type": "artifact",
"artifact_type": "summary",
"delta": "### 核心洞察\n- **情绪模式**: ",
"accumulated_length": 35
},
"seq": 2030,
"timestamp": 1704067300000
}

3.5.5 心跳响应

{
"type": "control",
"payload": {
"action": "pong"
},
"seq": 2003,
"timestamp": 1704067230010,
"ack_seq": 1002
}

3.5.6 错误消息

{
"type": "error",
"payload": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "请求过于频繁,请稍后再试",
"retry_after": 5000
},
"seq": 2004,
"timestamp": 1704067240000
}

错误码定义:

code说明建议处理
INVALID_SESSION会话无效或已过期重新创建会话
RATE_LIMIT_EXCEEDED请求频率超限等待 retry_after 后重试
LLM_ERRORLLM 服务异常提示用户重试
MEMORY_LOAD_FAILED记忆加载失败可继续对话,降级处理
CONNECTION_TIMEOUT连接超时重新连接

3.6 语音转文字 (ASR)

  • 路径: /api/v1/audio/transcribe
  • 方法: POST
  • 描述: 上传音频进行识别(支持中英混合、去口水词)。
  • 请求体: multipart/form-data (audio file/blob)
  • 响应体:
{
"text": "就是...嗯...我感觉压力很大。",
"cleaned_text": "我感觉压力很大。",
"duration_ms": 1500,
"confidence": 0.95
}

:v0.10 版本 ASR 使用独立 HTTP 接口。后续双工语音版本可通过 WebSocket 的 audio_chunk 消息类型实现流式 ASR。

3.7 双工语音扩展协议(预留)

以下协议为未来双工语音通话功能预留,v0.10 暂不实现。

3.7.1 开启双工语音模式

{
"type": "control",
"payload": {
"action": "start_duplex_voice",
"config": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
}
},
"seq": 1100,
"timestamp": 1704067400000
}

3.7.2 语音流数据

{
"type": "audio_chunk",
"payload": {
"data": "<base64-encoded-audio>",
"chunk_index": 42,
"is_final": false,
"vad_status": "speaking"
},
"seq": 1101,
"timestamp": 1704067400100
}

4. Memory 模块 (对外)

4.1 获取用户记忆列表

  • 路径: /api/v1/user/memory
  • 方法: GET
  • 描述: 获取"AI 记住了什么"列表,供用户查看和管理。
  • 请求参数:
    • category (可选): 按分类筛选,如 relationship, health
    • page: 页码,默认 1
    • page_size: 每页条数,默认 20
  • 响应体:
{
"categories": [
{"name": "relationship", "label": "关系", "count": 5},
{"name": "health", "label": "健康", "count": 3},
{"name": "career", "label": "职业", "count": 2}
],
"items": [
{
"id": "mem_001",
"type": "fact",
"category": "relationship",
"category_label": "关系",
"content": "和男友异地恋3年,他在上海工作",
"is_verified": false,
"created_at": "2026-01-10T10:00:00Z"
},
{
"id": "mem_002",
"type": "event",
"category": "relationship",
"category_label": "关系",
"content": "上周因为视频通话时间问题吵架了",
"is_verified": false,
"created_at": "2026-01-11T15:30:00Z"
}
],
"total": 10,
"page": 1,
"page_size": 20
}

4.2 获取用户画像

  • 路径: /api/v1/user/profile
  • 方法: GET
  • 描述: 获取用户画像信息(用于个人主页展示)。
  • 响应体:
{
"basic_info": {
"age": 28,
"gender": "female",
"occupation": "产品经理",
"location": "北京"
},
"communication_style": {
"expression": "细腻",
"emotion": "敏感",
"language": "偏文艺"
},
"core_concerns": ["异地恋问题", "职业倦怠"],
"updated_at": "2026-01-12T10:00:00Z"
}

4.3 编辑用户记忆

  • 路径: /api/v1/user/memory/:id
  • 方法: PATCH
  • 描述: 修改记忆内容或标记为已确认。
  • 请求体:
{
"content": "和男友异地恋4年了,他在上海工作",
"is_verified": true
}
  • 响应体:
{
"status": "success",
"item": {
"id": "mem_001",
"content": "和男友异地恋4年了,他在上海工作",
"is_verified": true,
"updated_at": "2026-01-12T14:00:00Z"
}
}

4.4 删除用户记忆

  • 路径: /api/v1/user/memory/:id
  • 方法: DELETE
  • 描述: 删除一条记忆(软删除,AI 将不再使用)。
  • 响应体:
{
"status": "success",
"message": "记忆已删除"
}

5. Insight 模块

5.1 生成对话总结 (Summary/Insight)

  • 路径: /api/v1/chat/session/:id/summary
  • 方法: POST
  • 描述: 触发 Agent 生成当前对话的 Insight 组件。
  • 响应体:
{
"summary_id": "sum_001",
"content_md": "### 核心洞察\n- **情绪模式**: 习惯通过购物缓解焦虑\n- **建议**: 尝试 5 分钟呼吸法",
"type": "artifact"
}

6. 历史管理模块

6.1 获取历史会话列表

  • 路径: /api/v1/chat/history
  • 方法: GET
  • 描述: 侧边栏展示,按时间排序。
  • 响应体:
{
"sessions": [
{
"session_id": "sess_9988",
"title": "关于深夜孤独感的对话",
"is_starred": true,
"updated_at": "2026-01-07T10:00:00Z"
}
]
}

6.2 会话操作 (Star/Rename)

  • 路径: /api/v1/chat/session/:id/meta
  • 方法: PATCH
  • 描述: 修改标题或收藏状态。
  • 请求体:
{
"title": "新的标题",
"is_starred": true
}
  • 响应体: 返回 status: updated

7. RAG 内部接口 (Backend ↔ RAG)

以下接口由 yolox-rag 服务提供,仅供 yolox-server 内部调用

7.1 Memory 检索

  • 路径: /internal/v1/memory/retrieve
  • 方法: POST
  • 描述: 动态 Prompt 组装时,获取用于 Module 1 的用户记忆。
  • 请求体:
{
"user_id": "uuid-xxx",
"query": "最近和男友沟通有问题",
"topic_category": "relationship",
"options": {
"include_profile": true,
"include_memories": true,
"include_last_summary": true,
"include_boundaries": true,
"memory_limit": 10,
"max_tokens": 3000
}
}
  • 响应体:
{
"status": "success",
"module1": {
"user_profile": {
"basic_info": {"age": 28, "gender": "female", "occupation": "产品经理"},
"communication_style": {"expression": "细腻", "emotion": "敏感"},
"core_concerns": ["异地恋问题", "职业倦怠"]
},
"memories": [
{
"id": "mem_001",
"type": "fact",
"category": "relationship",
"content": "和男友异地恋3年,他在上海工作",
"importance": 4,
"relevance_score": 0.92
},
{
"id": "mem_002",
"type": "event",
"category": "relationship",
"content": "上周因为视频通话时间问题吵架了",
"importance": 3,
"relevance_score": 0.88
}
],
"last_conversation_summary": {
"conversation_id": "conv_xxx",
"summary": "用户表达了对异地恋的疲惫感,提到最近沟通频率下降...",
"key_points": ["沟通频率下降", "考虑是否继续"]
},
"information_boundaries": [
{"question_type": "relationship_status", "is_known": true},
{"question_type": "partner_location", "is_known": true},
{"question_type": "age", "is_known": true},
{"question_type": "health_condition", "is_known": false}
],
"token_count": 2850
}
}

7.2 Memory 提取

  • 路径: /internal/v1/memory/extract
  • 方法: POST
  • 描述: 对话结束后,从对话内容中提取记忆并存储。
  • 请求体:
{
"user_id": "uuid-xxx",
"conversation_id": "conv_xxx",
"messages": [
{"role": "user", "content": "我今年28岁,和男友异地恋3年了..."},
{"role": "assistant", "content": "我能理解异地恋的不容易..."},
{"role": "user", "content": "是的,最近因为视频通话时间吵架了..."}
],
"topic_category": "relationship"
}
  • 响应体:
{
"status": "success",
"extraction_result": {
"profile_updated": true,
"profile_changes": {
"basic_info": {"age": 28},
"core_concerns": ["异地恋问题"]
},
"memories_created": [
{"id": "mem_003", "type": "fact", "content": "和男友异地恋3年"},
{"id": "mem_004", "type": "event", "content": "最近因为视频通话时间吵架"}
],
"memories_updated": [],
"boundaries_updated": ["relationship_status", "age"],
"summary_created": {
"id": "sum_001",
"key_points": ["异地恋3年", "沟通问题", "考虑是否继续"]
}
}
}

7.3 获取用户画像

  • 路径: /internal/v1/memory/profile/:user_id
  • 方法: GET
  • 描述: 获取用户完整画像(用于 Backend 代理给 Mobile)。
  • 响应体:
{
"status": "success",
"profile": {
"basic_info": {"age": 28, "gender": "female", "occupation": "产品经理", "location": "北京"},
"communication_style": {"expression": "细腻", "emotion": "敏感", "language": "偏文艺"},
"personality": {"mbti": null, "traits": ["内向", "共情力强"]},
"core_concerns": ["异地恋问题", "职业倦怠"],
"updated_at": "2026-01-12T10:00:00Z"
}
}

7.4 获取用户记忆列表

  • 路径: /internal/v1/memory/items/:user_id
  • 方法: GET
  • 描述: 获取用户记忆列表(用于 Backend 代理给 Mobile)。
  • 请求参数: category, page, page_size
  • 响应体:
{
"status": "success",
"items": [
{
"id": "mem_001",
"type": "fact",
"category": "relationship",
"content": "和男友异地恋3年,他在上海工作",
"is_verified": false,
"source_conversation_id": "conv_xxx",
"created_at": "2026-01-10T10:00:00Z"
}
],
"total": 15,
"page": 1,
"page_size": 20
}

7.5 编辑用户记忆

  • 路径: /internal/v1/memory/items/:memory_id
  • 方法: PATCH
  • 描述: 用户编辑/确认记忆。
  • 请求体:
{
"content": "和男友异地恋4年了,他在上海工作",
"is_verified": true
}
  • 响应体:
{
"status": "success",
"item": {
"id": "mem_001",
"content": "和男友异地恋4年了,他在上海工作",
"is_verified": true,
"updated_at": "2026-01-12T14:00:00Z"
}
}

7.6 删除用户记忆

  • 路径: /internal/v1/memory/items/:memory_id
  • 方法: DELETE
  • 描述: 用户删除记忆(软删除)。
  • 响应体:
{
"status": "success"
}

7.7 知识库检索

  • 路径: /internal/v1/knowledge/retrieve
  • 方法: POST
  • 描述: 动态 Prompt 组装时,获取 Module 2 的专家知识。
  • 请求体:
{
"query": "异地恋沟通问题怎么解决",
"topic_category": "relationship",
"limit": 5
}
  • 响应体:
{
"status": "success",
"knowledge": [
{
"content": "根据 Gottman 的关系理论,异地恋中的沟通质量比频率更重要...",
"type": "expert",
"source_ref": "Gottman - Seven Principles",
"relevance_score": 0.89
}
]
}

8. 基础设施依赖说明

8.1 服务间通信

┌──────────────────┐         gRPC/HTTP          ┌──────────────────┐
│ │ ──────────────────────────▶│ │
│ yolox-server │ │ yolox-rag │
│ (Backend) │ ◀──────────────────────────│ (RAG) │
│ │ Memory/Knowledge Data │ │
└──────────────────┘ └──────────────────┘
│ │
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ PostgreSQL │ │ PostgreSQL │
│ (用户/会话) │ │ (Memory) │
└──────────────────┘ └──────────────────┘


┌──────────────────┐
│ Milvus │
│ (向量检索) │
└──────────────────┘

8.2 实时通信 (WebSocket)

对话模块采用 WebSocket 实现全双工实时通信:

┌──────────────────┐                                   ┌──────────────────┐
│ Mobile App │ │ Backend │
│ │ │ │
│ ┌────────────┐ │ wss://api.yolox.ai/ws/chat │ ┌────────────┐ │
│ │ WS Client │◀─┼───────────────────────────────────┼─▶│ WS Server │ │
│ └────────────┘ │ │ └────────────┘ │
│ │ │ │
└──────────────────┘ └──────────────────┘
│ │
│ ← user_message (用户输入) │
│ → status_update (AI 状态) │
│ → ai_stream (流式回复) │
│ → ai_complete (回复完成) │
│ ↔ control (心跳/控制) │
│ │

选型理由:

维度WebSocketSSE
通信方向✅ 全双工❌ 单向(服务端→客户端)
双工语音扩展✅ 天然支持❌ 需重构
状态推送✅ 主动推送⚠️ 需额外接口
连接管理✅ 统一管理⚠️ 碎片化
延迟✅ 更低⚠️ 每次请求开销

连接管理策略:

  • 心跳间隔:30 秒
  • 重连策略:指数退避(1s, 2s, 4s, 8s, 最大 30s)
  • 超时时间:App 切后台 60s 后断开

8.3 其他依赖

  • 对象存储 (Cloudflare R2): 语音文件上传至 R2,数据库仅存储 URL。
  • 短信服务: 用于发送验证码到用户手机号。需要集成第三方短信服务商(如阿里云、腾讯云等)。验证码有效期 5-10 分钟,需实现频率限制。
  • 消息队列: Backend 触发 RAG 异步任务(如 Memory 提取)时使用。
  • 邀请码机制:
    • 邀请码由管理员通过后台系统创建,存储在 invitation_codes 表中。
    • 邀请码有效期 1 个月(从创建时间开始计算)。
    • 每个邀请码只能使用一次,使用后标记 is_used = true 并记录 used_byused_at