基于 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)

相关推荐
甘晴void19 小时前
我给 Magpie 做了个 macOS 桌宠:106 段动画,请求一多就亮灯
macos·electron·开源·deepseek·桌面宠物·magpie
大模型真好玩2 天前
DeepSeek Harness 插件的服务与事件监听详解
人工智能·agent·deepseek
东哥16882 天前
试了10个AI助手后,我发现只有这个能让我"睡后工作
deepseek
正在走向自律2 天前
Linux 服务器部署 DeepSeek 大模型完全指南(2026 版)
linux·运维·服务器·deepseek·部署deepseek·安装ollama·配置api服务
我才是银古2 天前
把 666 个会话摊开看:一份 DSH 使用经验与教训的复盘
ai·deepseek·dsh
猿究院--Cu-Sn合金2 天前
Spring Boot + DeepSeek 求职 Agent 实践:工具注册、多轮调用与简历 JD 对比
数据库·人工智能·spring boot·后端·deepseek
论文复现现场2 天前
DeepSeek V4.1 Flash 和 V4 Pro 有什么区别?API 价格、性能与迁移建议
java·服务器·人工智能·python·大模型api·deepseek·deepseek v4.1
承渊政道2 天前
飞牛NAS部署Hermes AI Agent:接入DeepSeek、微信与公网访问完整教程
人工智能·微信·nas·deepseek·hermes
一拳不是超人2 天前
用了两周,我给 DeepSeek Harness 写了 5 个插件
人工智能·ai编程·deepseek
论文复现现场2 天前
2026 低成本 AI Agent 模型怎么选?DeepSeek V4.1 Flash、Qwen3.8 Flash、GLM-5.3 Flash 对比
数据库·人工智能·qwen·ai agent·glm·deepseek