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

相关推荐
AC赳赳老秦12 小时前
网页公开附件自动采集:OpenClaw 批量下载页面内嵌 Word/Excel 附件,统一格式后结构化入库
java·python·word·php·excel·deepseek·openclaw
进军的码农1 天前
浪潮服务器怎么选?DeepSeek V4、GLM-5.2、Qwen3三大开源模型本地部署方案与代理商选购指南
大模型部署·deepseek·qwen3·浪潮服务器·gpu服务器·glm-5.2
yjm0021 天前
Reasonix 安装配置教程:DeepSeek 编程 Agent 入门指南
deepseek
gsls2008081 天前
Codex 桌面版接入 DeepSeek API 配置指南
codex·deepseek
AI英德西牛仔1 天前
手机文心怎么导出文档?AI 导出鸭一键解决格式崩塌与批量归档难题
人工智能·智能手机·excel·deepseek·ai导出鸭
飞哥数智坊2 天前
DeepSeek永久降价,78元到9元,这是要革谁的命?
deepseek
iini2 天前
nRF Connect SDK 开发新体验:VS Code + Claude Code + DeepSeek + Nordic MCP 全流程(蓝牙开发实例)
agent·ai编程·nrf connect sdk·zephyr·蓝牙开发·deepseek·mcp·claude code·nordic mcp
DS随心转小程序2 天前
文心文字怎么转为 word?告别繁琐排版操作,AI 导出鸭一站式完成文档转换工作
人工智能·word·豆包·deepseek·ai导出鸭
thesky1234562 天前
27届大模型面试准备(二十一):MoE 架构全攻略——稀疏激活、路由、负载均衡与专家并行
大模型·负载均衡·moe·deepseek·混合专家·专家并行·稀疏激活
还是鼠鼠4 天前
Spring AI连接DeepSeek与通义千问:application.yaml配置详解
java·通义千问·spring ai·deepseek