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

NextJS v14集成LLM代理API及NDJSON流处理技术问询

解决方案

1. 在服务器动作中处理NDJSON流

把ndjsonStream的处理逻辑放在服务器动作里,服务器端可以直接处理HTTP响应流,解析后返回可读流给客户端。

示例代码(app/actions.ts):

'use server';

import { ndjsonStream } from 'can-ndjson-stream';

export async function fetchLLMResponse(question: string): Promise<ReadableStream> {
  const response = await fetch('YOUR_LLM_PROXY_API_URL', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ question }),
  });

  if (!response.ok || !response.body) {
    throw new Error('Failed to fetch LLM response');
  }

  // 用ndjsonStream处理NDJSON格式的响应流
  return ndjsonStream(response.body);
}

2. 客户端表单组件触发请求

在客户端表单组件中调用服务器动作,获取流后传递给展示组件。

示例代码(app/components/QuestionForm.tsx):

'use client';

import { useState } from 'react';
import { fetchLLMResponse } from '../actions';
import StreamDisplay from './StreamDisplay';

export default function QuestionForm() {
  const [question, setQuestion] = useState('');
  const [responseStream, setResponseStream] = useState<ReadableStream | null>(null);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!question.trim()) return;

    try {
      const stream = await fetchLLMResponse(question);
      setResponseStream(stream);
    } catch (err) {
      console.error('Error fetching LLM response:', err);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={question}
          onChange={(e) => setQuestion(e.target.value)}
          placeholder="输入你的问题..."
        />
        <button type="submit">提问</button>
      </form>
      {responseStream && <StreamDisplay stream={responseStream} />}
    </div>
  );
}

3. 客户端组件渲染流式响应

创建专门的展示组件,读取流并逐块更新UI,实现打字机效果。

示例代码(app/components/StreamDisplay.tsx):

'use client';

import { useEffect, useState } from 'react';

type StreamDisplayProps = {
  stream: ReadableStream;
};

export default function StreamDisplay({ stream }: StreamDisplayProps) {
  const [content, setContent] = useState('');

  useEffect(() => {
    const reader = stream.getReader();
    const decoder = new TextDecoder();

    async function readStream() {
      try {
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

          // 解析单个NDJSON块(根据你的API返回结构调整字段)
          const data = JSON.parse(decoder.decode(value));
          setContent(prev => prev + data.content);
        }
      } catch (err) {
        console.error('Error reading stream:', err);
      } finally {
        reader.releaseLock();
      }
    }

    readStream();

    return () => {
      reader.cancel();
    };
  }, [stream]);

  return <div className="llm-response">{content}</div>;
}

关键说明

  • 服务器动作负责跨域请求、NDJSON流解析,将处理后的可读流返回给客户端,简化客户端逻辑。
  • 客户端通过ReadableStream.getReader()逐块读取数据,解码后解析JSON,逐步更新UI。
  • 两端都加入错误捕获,避免流读取失败导致页面崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:17:09