# LangChain 统一改造计划 ## 目标 将项目从"直接 API 调用"模式,迁移到"LangChain 统一调用"模式,实现: 1. LLM、TTS、Image、Video 统一接口 2. 自动模型切换 3. LangGraph 流程编排 ## 当前状态 ### ✅ 已完成 - Text 模型(qwen3.6-plus、qwen3.5-flash、MiniMax-M2.7、doubao-seed-2.0-code)已配置在 `models.json` - 通过 `ChatOpenAI` + `baseURL` 方式调用(OpenAI-compatible) - 模型验证器 `models-validator.ts` 可批量验证模型 ### ❌ 待改造 - TTS:`AliyunTTSProvider` 直接 axios 调用 - Image:MiniMax 直接 API - Video:MiniMax 直接 API - LangGraph:直接 axios 调用 LLM,未使用 LangChain Tool --- ## 阶段一:统一 LLM 调用(已完成 ✅) ### 目标 所有 Text 模型通过 LangChain `ChatOpenAI` 统一调用 ### 配置结构 ```json { "vendors": { "bailian": { "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1", "apiKey": "sk-xxx", "apiType": "openai-chat", "models": [...] }, "minimax": { ... }, "volcengine": { ... } } } ``` ### 涉及文件 - `src/config/models.json` - 厂商/模型配置 ✅ - `src/config/index.ts` - 配置读取逻辑 ✅ - `src/services/llm/index.ts` - LLM 服务(getLLM/callLLM) ✅ - `src/config/models-validator.ts` - 模型验证器 ✅ --- ## 阶段二:TTS 包装成 LangChain Tool ### 目标 TTS Provider 实现 `Tool` 接口,可在 LangGraph 节点中调用 ### 实现方式 #### 1. 定义 TTS Tool 接口 ```typescript import { Tool } from '@langchain/core/tools'; interface TTSResult { audioUrl: string; duration: number; } // TTS Tool 包装 const ttsTool = new Tool({ name: "text_to_speech", description: "将文本转换为语音,输入文本返回音频URL", returnDirect: true, args: z.object({ text: z.string().describe("要转换的文本"), voice: z.string().optional().describe("音色ID"), }), async invoke(input: { text: string; voice?: string }) { const provider = new AliyunTTSProvider(); return await provider.synthesize(input.text, input.voice || 'Cherry'); }, }); ``` #### 2. 更新 TTS Provider - 路径:`src/modules/tts/aliyun.provider.ts` - 修改为支持 Tool 调用格式 #### 3. MiniMax TTS 支持 - 当前 MiniMax TTS 未集成,需新增 Provider - 路径:`src/modules/tts/minimax.provider.ts` ### 涉及文件 - `src/modules/tts/aliyun.provider.ts` - 修改 - `src/modules/tts/minimax.provider.ts` - 新增 - `src/tools/tts.tool.ts` - Tool 封装 - `src/config/models.json` - 新增 tts 工具定义 --- ## 阶段三:Image 生成包装成 LangChain Tool ### 目标 Image 模型(MiniMax-image-01)包装成 Tool ### 实现方式 ```typescript const imageTool = new Tool({ name: "image_generation", description: "根据文本描述生成图片", args: z.object({ prompt: z.string().describe("图像描述"), model: z.string().optional(), }), async invoke(input: { prompt: string }) { const provider = new MiniMaxImageProvider(); return await provider.generate(input.prompt); }, }); ``` ### 涉及文件 - `src/modules/image/minimax.provider.ts` - 新增 - `src/tools/image.tool.ts` - Tool 封装 --- ## 阶段四:Video 生成包装成 LangChain Tool ### 目标 Video 模型(MiniMax-Hailuo-02)包装成 Tool ### 实现方式 ```typescript const videoTool = new Tool({ name: "video_generation", description: "根据文本描述生成视频", args: z.object({ prompt: z.string().describe("视频描述"), model: z.string().optional(), }), async invoke(input: { prompt: string }) { const provider = new MiniMaxVideoProvider(); return await provider.generate(input.prompt); }, }); ``` ### 涉及文件 - `src/modules/video/minimax.provider.ts` - 新增 - `src/tools/video.tool.ts` - Tool 封装 --- ## 阶段五:LangGraph 流程编排改造 ### 目标 将书籍生成流程从"手动 axios 调用"改为"LangGraph 节点调用 Tool" ### 当前流程(book-langgraph.ts) ```typescript // 当前:直接 axios 调用 async function callLLM(prompt: string) { const response = await axios.post(apiUrl, {...}); return response.data.output.text; } ``` ### 改造后 ```typescript import { ChatOpenAI } from '@langchain/openai'; import { ttsTool, imageTool } from '../../tools'; // LLM 作为 LangChain 实例 const llm = new ChatOpenAI({ model: modelId, apiKey: apiKey, configuration: { baseURL: baseUrl }, temperature: 0.7, }); // LangGraph 节点使用 Tool async function llmNode(state: BookState) { const result = await llm.invoke(state.task); return { text: result.content }; } async function ttsNode(state: BookState) { const audio = await ttsTool.invoke(state.text); return { audioUrl: audio }; } ``` ### 涉及文件 - `src/modules/book-generator/langgraph/book-langgraph.ts` - 重构 - `src/tools/index.ts` - 统一导出所有 Tool --- ## 阶段六:自动模型切换增强 ### 目标 Tool 调用失败时自动切换到备用模型 ### 实现方式 在 `shouldSwitchModel` 基础上,增加 Tool 级别的重试和切换逻辑 ```typescript async function invokeWithFallback( tool: Tool, input: any, modelType: 'text' | 'tts' | 'image' | 'video' ) { const models = config.models.getModelsByType(modelType); for (const model of models) { try { return await tool.invoke(input, { config: { model: model.id } }); } catch (error) { if (!shouldSwitchModel(error)) throw error; console.log(`[Tool] ${model.id} 失败,切换到 ${model.id}`); } } throw new Error(`所有 ${modelType} 模型均不可用`); } ``` --- ## 执行顺序 ``` 阶段一:统一 LLM 调用 → 已完成 ✅ 阶段二:TTS Tool → 待执行 阶段三:Image Tool → 待执行 阶段四:Video Tool → 待执行 阶段五:LangGraph 改造 → 待执行(依赖阶段二三四) 阶段六:自动切换增强 → 待执行 ``` --- ## 风险与注意事项 1. **TypeScript LangChain Tool 支持有限** - LangChain JS 生态不如 Python 完善 - Tool 接口可能需要 polyfill 2. **TTS/Image/Video 不是 OpenAI-compatible** - 无法直接用 ChatOpenAI 调用 - 必须包装成 Tool 间接调用 3. **API 兼容性** - MiniMax API: `https://api.minimax.chat/v1/chat/completions` ✅ 已验证 - 阿里云 TTS: `https://dashscope.aliyuncs.com/api/v1/services/audio/speech/synthesis` - 需验证 4. **改动范围** - 涉及多个 Provider 文件修改 - LangGraph 流程需要重新测试 - 建议分阶段提交 --- ## 后续优化方向 1. **多模型并行**:一个任务同时调用多个模型,取最快结果 2. **成本优化**:根据任务类型选择最便宜的模型 3. **流式输出**:Text/TTS 都支持流式 4. **结果缓存**:相同 prompt 缓存结果 --- ## 参考资料 - [LangChain Python TTS Tool](https://python.langchain.com/docs/integrations/tools/) - [LangChain JS Tool 文档](https://js.langchain.com/docs/integrations/tools/) - [LangGraph 状态管理](https://langchainai.github.io/langgraphjs/) - [阿里云 TTS API 文档](https://help.aliyun.com/zh/model-studio/qwen-tts) - [MiniMax API 文档](https://www.minimaxi.com/document)