Angular 16中LangChain的llm.predict调用OpenAI返回空结果排查
问题原因与解决方案
问题原因
你在Angular(浏览器环境)中使用了为NodeJS设计的OpenAI类,该类依赖NodeJS专属API(如Node版fetch、文件系统模块等),在浏览器中运行会出现兼容性问题,导致返回空结果。同时,直接在前端硬编码OpenAI API密钥存在严重安全风险,密钥会被用户轻易获取。
解决方案
1. 替换为浏览器兼容的ChatOpenAI类
LangChain提供了适配浏览器环境的ChatOpenAI类,替换原有的OpenAI类即可解决兼容性问题:
import { ChatOpenAI } from "langchain/chat_models/openai"; import { HumanMessage } from "langchain/schema"; @Injectable({ providedIn: 'root' }) export class ChatService { private chatModel: ChatOpenAI; constructor() { this.chatModel = new ChatOpenAI({ openAIApiKey: "你的API密钥", // 后续需迁移至后端 modelName: "gpt-3.5-turbo", temperature: 0, verbose: true }); } async simplePromptTest() { const result = await this.chatModel.call([ new HumanMessage("Israel's capital is") ]); console.log('Completion returned in simplePromptTest: ', result.content); return result.content; } }
2. 移除前端硬编码的API密钥(关键)
前端直接暴露API密钥会导致泄露,正确做法是通过后端转发请求:
- 搭建后端接口(如NodeJS/Express),由后端调用OpenAI API并返回结果
- Angular服务调用自己的后端接口,而非直接请求OpenAI
示例后端代码(NodeJS/Express):
const express = require('express'); const { OpenAI } = require('langchain/llms/openai'); const app = express(); app.use(express.json()); const llm = new OpenAI({ openAIApiKey: "你的API密钥", modelName: "gpt-3.5-turbo", temperature: 0 }); app.post('/api/chat', async (req, res) => { const { prompt } = req.body; const result = await llm.predict(prompt); res.json({ result }); }); app.listen(3000, () => console.log('Backend running on port 3000'));
修改后的Angular服务:
import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ChatService { constructor(private http: HttpClient) { } async simplePromptTest() { const response = await this.http.post<{ result: string }>('http://localhost:3000/api/chat', { prompt: "Israel's capital is" }).toPromise(); console.log('Completion returned in simplePromptTest: ', response?.result); return response?.result; } }
3. 配置Angular Polyfills(按需)
若遇到global未定义等依赖错误,在src/polyfills.ts中添加:
(window as any).global = window;
同时确保tsconfig.json的编译目标版本足够高:
{ "compilerOptions": { "target": "ES2020", // 其他配置... } }
内容的提问来源于stack exchange,提问作者Mor Sagmon
相关产品推荐
相关产品推荐

