🚀 基于 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 withnode >=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)