基于 Ollama 的大模型流式响应实践

🚀 基于 Ollama 的大模型流式响应实践总结

本文记录了在本地使用 Ollama 调用大模型(如 DeepSeek)时,如何通过 Node.js 实现流式响应,并通过前端进行实时显示的实践过程与问题解决方案。 页面如下:


🧠 项目背景

我们基于 Ollama 部署本地大语言模型(如 deepseek-r1:7b),前端通过 AJAX 请求向后端发送 prompt,后端调用 Ollama 的 /api/chat 接口,采用 流式返回(stream: true) 的方式,实现模型逐词输出,提升用户体验。


🛠️ 技术栈

  • 后端:Node.js (CommonJS)
  • 模型接口:Ollama 本地 API
  • 前端:原生 JS / 任意框架(如 React)
  • 请求库:node-fetch(需注意 ESM 兼容性)
  • 数据传输协议:SSE(Server-Sent Events)

🧩 常见问题与解决

❌ 报错:require() of ES Module not supported

bash 复制代码
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported.

原因node-fetch@3+ 是 ESM 模块,不再支持 CommonJS 的 require()

解决方案

  • 使用动态导入:const fetch = (await import('node-fetch')).default
  • 或使用 node-fetch@2(仍支持 CommonJS)

❌ 报错:response.body.getReader is not a function

该错误说明当前返回的 response.body 不是一个 ReadableStream。

排查方向

  • 确保模型接口启用了 "stream": true
  • 确保使用的是支持 ReadableStream 的 fetch(如 node-fetch@3 且为 ESM,或用原生 fetch with node >=18

✅ 后端处理方式(SSE 流式传输)

js 复制代码
app.post('/chat', async (req, res) => {
  const { prompt } = req.body;

  const response = await fetch('http://localhost:11434/api/chat', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'deepseek-r1:7b',
      messages: [{ role: 'user', content: prompt }],
      stream: true,
    }),
  });

  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { value, done } = await reader.read();
    if (done) {
      res.write('data: [DONE]\n\n');
      break;
    }

    const chunk = decoder.decode(value, { stream: true });
    const lines = chunk.split('\n').filter(Boolean);
    for (const line of lines) {
      try {
        const json = JSON.parse(line);
        res.write(`data: ${json.message?.content || ''}\n\n`);
      } catch (err) {
        continue;
      }
    }
  }
});

✅ 前端接收方式(SSE)

js 复制代码
const eventSource = new EventSource('/chat');

eventSource.onmessage = function (event) {
  console.log('Received:', event.data);
  if (event.data === '[DONE]') {
    eventSource.close();
  } else {
    // 追加 event.data 到聊天窗口
  }
};

🔍 模型返回示例

json 复制代码
{
  "model": "deepseek-r1:7b",
  "message": {
    "role": "assistant",
    "content": "Hello"
  },
  "done": false
}

返回为逐块数据,直到:

json 复制代码
{
  "done": true,
  "done_reason": "stop"
}

✅ 模型可用性测试(curl)

bash 复制代码
curl http://localhost:11434/api/chat \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-r1:7b",
    "messages": [{"role": "user", "content": "Hello"}],
    "stream": true
  }'

如出现:

json 复制代码
{"error":"model \"llama3\" not found, try pulling it first"}

请使用正确的模型名,如 deepseek-r1:7b


🎯 总结

  • 使用 Ollama 本地部署大模型是开发 LLM 应用的高效方式。
  • 使用 stream: true 可大幅提升响应体验。
  • 后端使用 SSE 向前端推送数据是简单高效的方式。
  • 需注意 CommonJS 与 ESM 模块的兼容问题。

以实际的代码为准,欢迎交流探讨


🧑‍💻 作者:byteLee

📅 时间:2025 年

📁 项目地址:(https://gitee.com/yadalihongye/local-ds-chat)

相关推荐
胡耀超1 天前
开源生态与技术民主化 - 从LLaMA到DeepSeek的开源革命(LLaMA、DeepSeek-V3、Mistral 7B)
人工智能·python·神经网络·开源·大模型·llama·deepseek
Lethehong2 天前
DeepSeek-V3.1-Terminus:蓝耘API+CherryStudio实测国产最新开源模型,推理能力竟让我后背发凉
人工智能·大模型·deepseek·蓝耘元生代·蓝耘maas·ai ping
大模型真好玩2 天前
深入浅出LangGraph AI Agent智能体开发教程(八)—LangGraph底层API实现ReACT智能体
人工智能·agent·deepseek
canonical_entropy3 天前
一份关于“可逆计算”的认知解码:从技术细节到哲学思辨的完整指南
后端·低代码·deepseek
用户51681661458413 天前
使用[DeepSeek]快速定位nginx前端部署后报错:500 Internal Server Error nginx/1.29.1
nginx·deepseek
汉密士202401015 天前
DeepSeek对数学工具的分类(2025.1.13)
人工智能·deepseek·数学工具·数学结构
AI大模型5 天前
DeepSeek + RAGFlow 构建个人知识库,解决AI胡说八道
llm·agent·deepseek
OliverYeung5 天前
【AskAI系列课程】:P3.Agno从阿里云百炼知识库中检索知识库片段并回答用户问题
人工智能·ai·llm·rag·agentic·deepseek·agno
IvorySQL7 天前
PostgreSQL 全表 count 优化实践:从 SeqScan 痛点分析到 heapam 改进与性能突破
数据库·postgresql·oracle·deepseek·ivorysql