You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js Pages Router中OpenAI GPT助手无输出问题求助

解决Next.js Pages Router中useAssistant钩子无响应的问题

问题根源

  1. 响应被覆盖:API路由中调用AssistantResponse处理流式响应后,又通过res.status(200).json(...)发送了JSON响应,直接中断流式传输,导致前端useAssistant无法接收助手回复数据。
  2. AssistantResponse参数错误:Pages Router环境下,AssistantResponse需要绑定req和res对象才能正确处理流式输出,原代码未传入这两个关键参数。
  3. 工具调用未处理:当助手触发工具调用时,原代码直接抛出错误,导致流处理中断。

修复后的API路由代码(pages/api/assistant/index.tsx)

import { NextApiRequest, NextApiResponse } from "next";
import { AssistantResponse } from "ai";
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY || "",
});

export const maxDuration = 30;

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" });
  }

  try {
    const input: {
      threadId: string | null;
      message: string;
    } = req.body;

    const threadId = input.threadId ?? (await openai.beta.threads.create({})).id;

    const createdMessage = await openai.beta.threads.messages.create(threadId, {
      role: "user",
      content: input.message,
    });

    // 关键修改:传入req和res绑定响应流
    await AssistantResponse(
      { req, res, threadId, messageId: createdMessage.id },
      async ({ forwardStream, sendDataMessage }) => {
        let runStream = openai.beta.threads.runs.stream(threadId, {
          assistant_id:
            process.env.ASSISTANT_ID ??
            (() => {
              throw new Error("ASSISTANT_ID is not set");
            })(),
        });

        let runResult = await forwardStream(runStream);

        while (
          runResult?.status === "requires_action" &&
          runResult.required_action?.type === "submit_tool_outputs"
        ) {
          const tool_outputs = runResult.required_action.submit_tool_outputs.tool_calls.map(
            (toolCall: any) => {
              const parameters = JSON.parse(toolCall.function.arguments);

              switch (toolCall.function.name) {
                // 这里添加你的工具处理逻辑,示例:
                // case "get_user_stats":
                //   return {
                //     tool_call_id: toolCall.id,
                //     output: JSON.stringify({ total: 100 })
                //   };
                default:
                  // 避免抛出错误中断流,返回默认提示
                  return {
                    tool_call_id: toolCall.id,
                    output: JSON.stringify({ error: `未实现工具调用:${toolCall.function.name}` })
                  };
              }
            },
          );

          runResult = await forwardStream(
            openai.beta.threads.runs.submitToolOutputsStream(threadId, runResult.id, {
              tool_outputs,
            }),
          );
        }
      },
    );

    // 移除该行:AssistantResponse已处理响应,无需重复发送JSON
    // res.status(200).json({ threadId, messageId: createdMessage.id });
  } catch (error) {
    console.error("Error handling request:", error);
    res.status(500).json({ error: "Internal Server Error" });
  }
}

前端组件注意事项(components/Statistics.tsx)

  1. 正确解析消息内容:useAssistant返回的message.content是内容块数组,需正确提取文本。示例解析函数:
function parseContent(content: any) {
  const textContent = content
    .filter((block: any) => block.type === 'text')
    .map((block: any) => block.text.value)
    .join('');
  
  // 根据助手返回的内容格式调整解析逻辑,这里假设返回JSON
  try {
    return JSON.parse(textContent);
  } catch (e) {
    return { whatsWorking: textContent, whatsNeedsImproving: '' };
  }
}
  1. 监听状态变化:提交消息后status会变为'streaming',完成后变为'idle',可据此添加加载提示。

内容的提问来源于stack exchange,提问作者Evan Gordon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:22:02