Ionic7+Node.js集成OpenAI Assistant API遇[object object]响应问题
问题描述
使用Ionic Framework 7开发企业助手聊天机器人,接入OpenAI Assistant时遇到问题:发送prompt后,机器人返回[object object]。
Node.js服务端代码(server.js)
import express from "express"; import * as dotenv from "dotenv"; import cors from "cors"; import OpenAI from "openai"; dotenv.config(); const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, organization: process.env.OPENAI_ORG_ID, project: process.env.OPENAI_PROJECT_ID, }); const assistantId = process.env.OPENAI_ASSISTANT_ID; const app = express(); app.use(cors()); app.use(express.json()); async function createThread() { const thread = await openai.beta.threads.create(); return thread.id; } async function addMessage(threadId, prompt) { const response = await openai.beta.threads.messages.create(threadId, { role: "user", content: prompt.substring(0, 1000) }); return response; } async function runAssistant(threadId) { const response = await openai.beta.threads.runs.create(threadId, { assistant_id: assistantId }); return response; } async function getRunStatus(threadId, runId) { const runObject = await openai.beta.threads.runs.retrieve(threadId, runId); return runObject; } app.get("/", async (req, res) => { res.status(200).send({ message: 'Sea bienvenido a nuestro Chatbot', }); }); app.post("/", async (req, res) => { try { const prompt = req.body.prompt; const threadId = await createThread(); await addMessage(threadId, prompt); const runResponse = await runAssistant(threadId); const runId = runResponse.id; const pollingInterval = setInterval(async () => { const runStatus = await getRunStatus(threadId, runId); if (runStatus.status === 'completed') { clearInterval(pollingInterval); const messagesList = await openai.beta.threads.messages.list(threadId); const botMessage = messagesList.data.find(message => message.role === "assistant"); const botResponse = botMessage ? botMessage.content : "Lo siento, no pude entender tu pregunta. ¿Podrías ser más específico?"; res.status(200).send({ bot: botResponse }); } else if (runStatus.status === 'failed' || runStatus.status === 'expired') { clearInterval(pollingInterval); res.status(500).send({ error: "Error en la ejecución del asistente." }); } }, 5000); } catch (error) { console.log(error); res.status(500).send({ error: error.message }); } }); app.listen(3000, () => console.log('Server is running on port: http://localhost:3000') );
Ionic页面代码(page.ts)
import { Component, OnInit, ViewChild } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { IonContent } from '@ionic/angular'; import { Message } from 'src/app/models/message.model'; import { OpenaiService } from 'src/app/services/openai.service'; @Component({ selector: 'app-tab4-faq', templateUrl: './tab4-faq.page.html', styleUrls: ['./tab4-faq.page.scss'], }) export class Tab4FaqPage implements OnInit { @ViewChild(IonContent, { static: false }) content!: IonContent; messages: Message[] = []; form = new FormGroup({ prompt: new FormControl('', [Validators.required]), }); loading: boolean = false; constructor(private openAi: OpenaiService) {} ngOnInit() {} submit() { if (this.form.valid) { let prompt = this.form.value.prompt as string; // === 用户消息 === let userMsg: Message = { sender: 'me', content: prompt }; this.messages.push(userMsg); this.scrollToBottom(); this.form.reset(); this.form.disable(); this.loading = true; this.openAi.sendQuestion(prompt).subscribe({ next: (res: any) => { this.loading = false; let botMsg: Message = { sender: 'bot', content: res.bot }; this.messages.push(botMsg); this.scrollToBottom(); this.form.enable(); }, error: (error: any) => { console.log(error); }, }); } } scrollToBottom() { this.content.scrollToBottom(2000); } }
问题原因及解决方法
返回[object object]的核心原因是:服务端返回的botResponse是对象数组,前端直接将其作为字符串渲染,导致显示默认的对象字符串表示。
OpenAI Assistant返回的botMessage.content是一个数组,每个元素包含type字段(如text)和对应内容结构(文本类型会有text.value字段)。
修改服务端代码(server.js)
在获取botResponse时,需要提取出纯文本内容:
// 替换原botResponse的赋值代码 const botResponse = botMessage ? botMessage.content .filter(item => item.type === 'text') // 过滤出文本类型内容 .map(item => item.text.value) // 提取文本值 .join('\n') // 拼接成完整字符串 : "Lo siento, no pude entender tu pregunta. ¿Podrías ser más específico?";
前端验证
修改后服务端返回的是纯字符串,前端现有逻辑可直接正常显示,无需额外修改。
额外优化建议
- 不要每次请求创建新线程,建议将threadId存储在前端会话中,保持对话上下文连贯性。
- 缩短轮询间隔(如调整为1000ms),提升响应速度。
- 若助手可能返回图片等非文本内容,需在服务端和前端添加对应类型的处理逻辑。
内容的提问来源于stack exchange,提问作者FRANK
相关产品推荐
相关产品推荐

