| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- # Tolan AI 英语语音助手 - 开发规则
- ## 项目概述
- - **后端**: FastAPI + Python 3.11+ + WebSocket
- - **前端**: React 18 + TypeScript + Vite + Ant Design
- - **AI服务**: 阿里云 DashScope (STT/LLM/TTS)
- - **架构**: 实时语音对话流水线 (STT → LLM → TTS)
- ---
- ## 代码生成原则
- ### 文档规则
- - ❌ 避免生成冗长的 Markdown 文档
- - ✅ 代码优先,注释简洁
- - ✅ 必要文档:配置说明、API定义(列表形式)
- - ✅ 文档格式:表格 > 列表 > 段落
- - ✅ **文档生成路径规则**:
- - 项目文档 → `项目文档/` 目录
- - 后端文档 → `backend/文档/` 目录
- - 前端文档 → `frontend/docs/` 目录(如需要)
- - 配置文档 → 对应模块根目录(如 `backend/ENV_CONFIG.md`)
- ### 代码风格
- - **Python**: 类型提示、async/await、异常处理必需
- - **TypeScript**: 严格类型、接口定义、错误边界
- - **命名**: 英文、语义化、统一风格(snake_case/camelCase)
- - **注释**: 仅对复杂逻辑、性能优化、临时方案添加
- ---
- ## 后端开发规则
- ### FastAPI 结构
- ```python
- # 路由定义
- @app.websocket("/ws")
- async def endpoint(websocket: WebSocket): ...
- # 类型定义(必需)
- from pydantic import BaseModel
- class Message(BaseModel):
- type: str
- data: dict
- ```
- ### 异步编程
- - 所有 I/O 操作使用 `async/await`
- - 使用 `asyncio.to_thread()` 包装同步库
- - WebSocket 消息处理异步化
- ### 配置管理
- - 所有配置从 `.env` 读取
- - 使用 `pydantic-settings` 管理
- - 必需项无默认值,可选项提供默认值
- ### AI 服务集成
- ```python
- # DashScope API 调用模式
- import dashscope
- dashscope.api_key = settings.DASHSCOPE_API_KEY
- # 流式处理
- async for chunk in ai_service.generate_stream(text):
- await websocket.send_json(chunk)
- ```
- ### 错误处理
- ```python
- try:
- result = await api_call()
- except Exception as e:
- logger.error(f"Error: {e}")
- await send_error(request_id, str(e))
- ```
- ---
- ## 前端开发规则
- ### React + TypeScript
- ```typescript
- // 类型定义(必需)
- interface Message {
- type: string;
- requestId: string;
- data: unknown;
- }
- // 组件定义
- export const Component: React.FC<Props> = ({ ... }) => {
- // Hooks
- const [state, setState] = useState<Type>(initial);
-
- // 处理函数
- const handleEvent = useCallback(() => { ... }, [deps]);
-
- return <UI />;
- };
- ```
- ### WebSocket 通信
- ```typescript
- // 发送消息
- ws.send(JSON.stringify({ type, requestId, data }));
- // 接收消息
- ws.onmessage = (event) => {
- const message: Message = JSON.parse(event.data);
- handleMessage(message);
- };
- ```
- ### 状态管理 (Zustand)
- ```typescript
- export const useStore = create<State>((set) => ({
- value: initial,
- update: (newValue) => set({ value: newValue }),
- }));
- ```
- ### 音频处理
- ```typescript
- // 录音
- const recorder = new Recorder({ sampleRate: 16000 });
- recorder.start();
- // Base64 编码
- const base64 = btoa(String.fromCharCode(...audioData));
- ```
- ### 移动端适配 (postcss-px-to-viewport)
- #### 配置信息
- - **设计稿基准**: 375px × 812px (iPhone X/11/12/13/14)
- - **转换单位**: vw (viewport width)
- - **自动转换**: CSS 文件中的 px 自动转换为 vw
- - **排除目录**: node_modules(第三方组件不转换)
- #### 核心规则
- ##### ✅ CSS 文件样式(自动转换)
- ```css
- /* 直接写 px,插件自动转换为 vw */
- .box {
- width: 100px; /* → 26.66667vw */
- padding: 16px; /* → 4.26667vw */
- font-size: 14px; /* → 3.73333vw */
- }
- ```
- ##### ✅ 内联样式(手动转换)
- ```typescript
- import { px2vw } from '@/utils/viewport';
- // 必须使用 px2vw() 函数
- <div style={{
- width: px2vw(100), // ✅ 正确
- padding: px2vw(16), // ✅ 正确
- }}>
- // ❌ 错误:内联样式不会自动转换
- <div style={{ width: '100px' }}> // 保持 100px
- ```
- ##### ✅ 固定尺寸元素(不转换)
- ```css
- /* 使用大写 PX 避免转换 */
- .icon {
- width: 20PX; /* 保持 20px */
- height: 20PX; /* 保持 20px */
- }
- /* 或添加 .ignore 类 */
- .ignore {
- width: 20px; /* 不会转换 */
- }
- ```
- ##### ❌ 1px 边框问题
- ```css
- /* 当前配置:1px 会转换为 vw */
- /* 如需真实 1px(如分隔线),使用大写 PX */
- .divider {
- border: 1PX solid #ddd; /* 保持 1px */
- }
- /* 或使用 transform 方案 */
- .hairline::after {
- height: 1px;
- transform: scaleY(0.5);
- }
- ```
- #### 使用场景
- ##### 场景 1: 动态计算的内联样式
- ```typescript
- // ❌ 错误
- const width = 100;
- <div style={{ width: `${width}px` }}>
- // ✅ 正确
- import { px2vw } from '@/utils/viewport';
- const width = 100;
- <div style={{ width: px2vw(width) }}>
- ```
- ##### 场景 2: 响应式最大/最小值
- ```css
- /* 结合使用 vw 和固定值 */
- .container {
- width: 100vw;
- max-width: 430PX; /* 使用 PX 限制最大宽度 */
- }
- ```
- ##### 场景 3: 媒体查询
- ```css
- /* 媒体查询中的 px 不会转换(已配置 mediaQuery: false) */
- @media (min-width: 768px) {
- .content {
- max-width: 430px; /* 保持 px */
- }
- }
- ```
- ##### 场景 4: TouchTarget 最小尺寸
- ```typescript
- // Apple HIG 标准:最小 44px
- // 这些 px 会被转换为 vw
- <button style={{
- minWidth: px2vw(44),
- minHeight: px2vw(44),
- }}>
- ```
- ##### 场景 5: iOS 安全区域
- ```css
- /* env() 函数不受影响,正常工作 */
- .safe-area {
- padding-top: env(safe-area-inset-top);
- padding-bottom: env(safe-area-inset-bottom);
- }
- ```
- #### 禁止事项
- - ❌ 在 JS 中硬编码 vw 值
- - ❌ 混用多种适配方案(rem + vw)
- - ❌ 在媒体查询中依赖 px 自动转换
- - ❌ 内联样式忘记使用 px2vw()
- - ❌ 修改第三方组件样式(使用其原生方案)
- #### 调试技巧
- ```bash
- # 1. 查看转换后的 CSS
- npm run build
- # 检查 dist/assets/*.css
- # 2. 开发模式实时查看
- npm run dev
- # 浏览器开发者工具 → 检查元素 → Computed 样式
- # 3. 临时禁用转换
- /* px-to-viewport-ignore-next */
- .special {
- width: 100px; /* 这行不会转换 */
- }
- ```
- #### 工具函数
- ```typescript
- // frontend/src/utils/viewport.ts
- import { px2vw, px2vh } from '@/utils/viewport';
- px2vw(100) // → '26.66667vw' (基于 375px)
- px2vh(100) // → '12.31527vh' (基于 812px)
- ```
- ---
- ## API 集成规则
- ### DashScope STT
- - 模型: `qwen3-asr-flash-realtime`
- - 格式: PCM 16kHz mono
- - 流式识别: WebSocket API
- ### DashScope LLM
- - 模型: `qwen-turbo/qwen-plus`
- - 模式: 流式输出 (stream=True)
- - 提示词: 简化版优先
- ### DashScope TTS
- - 模型: `qwen3-tts-flash`
- - 音色: `Cherry` (女声)
- - 输出: PCM 24kHz
- - 速率控制: `TTS_MIN_INTERVAL` 避免限流
- ---
- ## WebSocket 消息协议
- ### 客户端 → 服务端
- ```typescript
- { type: "audio_chunk", requestId, data: base64, chunkIndex, sampleRate }
- { type: "audio_end", requestId, totalChunks }
- { type: "cancel", requestId }
- ```
- ### 服务端 → 客户端
- ```typescript
- { type: "text_result", requestId, text, isFinal }
- { type: "emotion", requestId, emotion }
- { type: "audio_response", requestId, data: base64, chunkIndex, isLast }
- { type: "error", requestId, code, message }
- ```
- ---
- ## 性能优化规则
- ### 后端优化
- - TTS 连接预热(启动时)
- - HTTP/2 连接池(httpx)
- - 流式处理(LLM+TTS 并行)
- - 动态超时(根据 STT 更新时间)
- ### 前端优化
- - 音频流式播放(边接收边播放)
- - WebSocket 断线重连
- - 组件懒加载 (React.lazy)
- - 防抖/节流(用户交互)
- ---
- ## 文档生成规范
- ### 文档类型与路径
- | 文档类型 | 生成路径 | 示例 |
- |---------|---------|------|
- | 项目架构/设计文档 | `项目文档/` | `项目文档/系统架构设计.md` |
- | API 文档 | `项目文档/` | `项目文档/前后端交互API文档.md` |
- | 需求文档 | `需求/` | `需求/用户需求.md` |
- | 后端技术文档 | `backend/文档/` | `backend/文档/数据库设计.md` |
- | 后端配置说明 | `backend/` | `backend/ENV_CONFIG.md` |
- | 前端技术文档 | `frontend/docs/` | `frontend/docs/组件设计.md` |
- | 部署运维文档 | `项目文档/` | `项目文档/部署指南.md` |
- ### 文档命名规则
- - 使用中文文件名(项目主要使用中文)
- - 描述清晰、简洁
- - 格式:`功能描述.md`
- ---
- ## 常见任务模板
- ### 添加新的 WebSocket 消息类型
- 1. `backend/models.py`: 定义 Pydantic 模型
- 2. `backend/websocket_handler.py`: 添加处理函数
- 3. `frontend/src/types/index.ts`: 定义 TypeScript 类型
- 4. `frontend/src/utils/websocket.ts`: 添加发送/接收逻辑
- ### 添加新的环境变量
- 1. `backend/.env`: 添加配置项
- 2. `backend/config.py`: 定义 Settings 字段
- 3. `backend/ENV_CONFIG.md`: 更新文档(仅列表)
- ### 添加新的 UI 页面
- 1. `frontend/src/pages/`: 创建页面组件
- 2. `frontend/src/router/`: 添加路由
- 3. 使用 Ant Design 组件,保持风格统一
- ### 生成技术文档
- 1. 确定文档类型(架构/API/配置/需求等)
- 2. 根据上表选择正确的生成路径
- 3. 使用表格格式(优先)
- 4. 内容控制在 100 行以内
- ---
- ## 禁止事项
- - ❌ 生成超过 100 行的 Markdown 文档
- - ❌ 在代码中使用 `any` 类型(TypeScript)
- - ❌ 同步阻塞 I/O 操作(后端)
- - ❌ 硬编码 API 密钥或敏感信息
- - ❌ 未处理的 Promise rejection
- - ❌ 未添加类型提示的函数(Python/TS)
- ---
- ## 调试技巧
- ```python
- # 后端日志
- print(f"[{request_id}] 🔍 Debug: {variable}")
- # 性能测试
- import time
- start = time.time()
- # ... code ...
- print(f"⏱️ Duration: {(time.time() - start)*1000:.1f}ms")
- ```
- ```typescript
- // 前端日志
- console.log('[WebSocket] Received:', message.type);
- console.time('Processing');
- // ... code ...
- console.timeEnd('Processing');
- ```
|