当前位置: 首页 > news >正文

ollama本地化部署deepseek/大模型及其api流式调用

Windows下使用 Ollama 安装并调用 DeepSeek 等大模型全流程(含API与Java流式调用)

一、Ollama 简介

Ollama 是一个轻量级本地大模型运行环境,可以在 Windows / macOS / Linux 上运行主流开源模型。它支持:

  • DeepSeek、Qwen、LLaMA、Phi-3、Gemma 等模型;
  • 本地推理,无需联网;
  • 提供 HTTP REST API
  • 支持 流式输出,适合集成前后端聊天应用。

二、环境准备与安装

1. 下载 Ollama 安装包

前往官网:

🔗 https://ollama.com/download

选择 Windows Installer (.exe) 下载。

安装完成后,Ollama 会自动在系统中注册命令行工具 ollama


2. 验证安装是否成功

打开 PowerShellCMD,执行:

ollama --version

如果输出版本号(例如 ollama 0.3.12),说明安装成功。


三、模型管理与路径调整

1. 默认模型存放位置

Ollama 默认会把模型文件放在:

C:\Users\<用户名>\.ollama\models

如果系统盘空间有限,可以修改模型文件路径。


2. 修改模型文件存储路径变更

2.1 迁移下载的模型

关闭 Ollama 服务:

taskkill /F /IM ollama.exe

移动模型文件夹:

move "C:\Users\<用户名>\.ollama" "D:\OllamaModels"

配置环境变量(让 Ollama 指向新目录):

打开 系统环境变量 → 新建:

变量名
OLLAMA_MODELSD:\LLM\models

或者使用命令行方式:

setx OLLAMA_MODELS "D:\LLM\models"

修改后需重启命令行窗口生效。

2.2 安装时就设定模型下载路径

可以在找到下载的文件(.exe)然后执行如下命令,在安装时即可默认更改下载模型的路径

OllamaSetup.exe /DIR="D:\LLM\models"

在这里插入图片描述

2.3 页面更改下载模型路径

打开桌面上ollama安装后的图标
ollama安装后的图标,找到设置-》更改模型下载位置
在这里插入图片描述


四、Ollama 服务启动与模型安装

1. 启动 Ollama 服务

执行命令:

ollama serve &  //&保持后台启动,不会因为窗口关闭就停止

默认监听在:

http://localhost:11434

✅ 2. 拉取 DeepSeek 模型

2.1 手动拉取模型

以 DeepSeek 为例:

ollama pull deepseek-coder

其它模型可选:

ollama pull deepseek-llm
ollama pull qwen2
ollama pull llama3
ollama pull gemma2

下载完成后,模型文件会保存在 OLLAMA_MODELS 所指的目录。

2.1 页面下载模型

当进行聊天的时候,选择的模型如果没有下载,后台会默认进行下载,等带下载完成后即可使用
在这里插入图片描述


✅ 3. 查看本地模型

ollama list

示例输出:

在这里插入图片描述


✅ 4. 测试模型运行

ollama run deepseek-r1:1.5b

进入交互模式:

>>> 帮我写一段Java代码,输出Hello World。

在这里插入图片描述


六、自定义模型构建与管理(Modelfile 教程)

除了直接使用官方模型(如 DeepSeek、Qwen、LLaMA 等),
Ollama 还支持通过 Modelfile 构建自定义模型。

你可以在现有模型基础上添加:

  • 自定义系统提示词(System Prompt)
  • 预定义上下文内容
  • 模型参数(如温度、top_p 等)
  • LoRA 微调文件

这样可以快速创建一个“专属助理”或“行业知识模型”。


1. 什么是 Modelfile?

Modelfile 类似于 Dockerfile,用来描述一个模型的构建规则。
一个简单示例如下:

FROM deepseek-coderPARAMETER temperature 0.7
PARAMETER top_p 0.9SYSTEM """
你是一个专业的Java开发助手,擅长Spring Boot和分布式系统设计。
请用清晰、准确的代码和注释回答问题。
"""# 可选:添加预置知识内容
MESSAGE """
你好!我是DeepSeek-Java助手,请问你需要我帮你写什么Java代码?
"""
  • FROM:指定基础模型。
  • PARAMETER:设定生成参数。
  • SYSTEM:定义模型的角色或系统提示词。
  • MESSAGE:定义模型启动时的初始输出。

2. 创建自定义模型

1. 生成Modefile文件

在Ollama中,Modelfile并非默认自动生成的文件,而是需要手动创建或通过命令导出的。如果找不到Modelfile,可能是因为你尚未导出模型配置或未手动创建,具体解决方法如下:

情况1:需要导出已下载模型的Modelfile

如果你想修改已下载的模型(如DeepSeek、Llama等)的配置,需要先通过ollama show命令导出该模型的Modelfile

  1. 列出已有的模型,确认模型名称和标签:

    ollama list
    

    例如,假设显示有deepseek-r1:1.5bdeepseek-coder:6b

  2. 导出模型的Modelfile
    执行以下命令,将模型的配置导出到本地文件(文件名可自定义,如my_modelfile):

    ollama show deepseek-r1:1.5b--modelfile > my_modelfile
    
    • 替换deepseek-r1:1.5b为你的模型名称(如llama3:8b)。
    • 执行后,当前目录会生成my_modelfile文件,这就是该模型的配置文件(包含TEMPLATE等关键信息)。
情况2:需要手动创建新的Modelfile

如果你想导入自己的模型或自定义新模型,需要手动创建Modelfile

  1. 在任意目录新建文本文件,命名为Modelfile(无后缀,或自定义名称如my_model.txt)。
  2. 按格式编写内容,例如基础结构:
    FROM /path/to/your/model.gguf  # 本地模型权重路径
    TEMPLATE "{{ .Prompt }} {{ .Response }}"  # 自定义提示词模板
    PARAMETER temperature 0.5
    
    具体格式参考Ollama官方文档的Modelfile语法。
常见问题解决
  • 提示“model not found”:确保模型名称正确(通过ollama list确认),且已成功下载(未下载的模型无法导出Modelfile)。
  • 导出后文件为空:可能是模型版本过旧或格式特殊,尝试更新模型(ollama pull 模型名)后重新导出。
  • 找不到导出的文件:检查命令执行的目录(默认在当前终端的工作目录),或通过ls(Linux/macOS)、dir(Windows)查看当前目录文件。

通过以上方法,可以获取或创建Modelfile,进而修改模型配置。

2. 根据Modefile文件创建新模型

打开my_modelfile,找到TEMPLATE字段,查看是否有引导模型输出思考过程的内容。例如:

# 原始模板可能包含类似内容(示例)
TEMPLATE """
用户问:{{ .Prompt }}
请先思考,再回答:
思考:...
回答:{{ .Response }}
"""

修改为仅输出最终回答的模板,例如:

# 修改后的模板(仅保留回答部分)
TEMPLATE """
{{ .Prompt }}
{{ .Response }}
"""

或根据DeepSeek模型的原生格式调整。

用修改后的Modelfile重新构建模型(自定义一个新名称,避免覆盖原模型):

ollama create deepseek-no-thinking -f my_modelfile
  • deepseek-no-thinking是新模型的名称,可自定义。

我这里是像做一个不带思考过程的大模型,于是我将原来安装的deepseek-r1:1.5b的模型的语法去除掉思考过程。

在这里插入图片描述

验证是否成功:

ollama list

输出示例:
在这里插入图片描述

使用新创建的模型,此时应不再输出“thinking”:

ollama run deepseek-no-thinking

通过以上步骤,即可去除Ollama调用DeepSeek模型时的“thinking”输出。


3. 删除模型

删除模型:

ollama rm deepseek-algo

重新构建(更新)模型:

ollama create deepseek-algo -f Modelfile --force

🌐 七、API 调用(REST 接口)

Ollama 启动后自动提供 API 服务。
默认接口地址为:

http://localhost:11434/api/generate

1. 基本调用示例(curl)

curl http://localhost:11434/api/generate -d '{"model": "deepseek-coder","prompt": "写一个Python程序读取CSV文件并统计行数。"
}'

返回结果:

{"model": "deepseek-coder","response": "```python\nimport csv\n...```","done": true
}

2. apipost调用

1.单次对话

在这里插入图片描述

2.多次对话

在这里插入图片描述
在这里插入图片描述

前后端流式调用,使用Nginx/Java后台做转发

3. 使用 WebFlux-JAVA后端

添加依赖(Maven):

 <!-- Spring WebFlux 核心依赖(响应式Web框架) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><!-- Reactor Netty(WebFlux默认的HTTP客户端/服务器) --><dependency><groupId>io.projectreactor.netty</groupId><artifactId>reactor-netty-core</artifactId></dependency>

示例代码:

1.流配置文件WebClientConfig
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;import java.time.Duration;
import java.util.concurrent.TimeUnit;
@Configuration
public class WebClientConfig {@Beanpublic WebClient efficientOllamaWebClient() {// 为旧版本Reactor Netty配置连接池ConnectionProvider connectionProvider = ConnectionProvider.builder("ollama-pool").maxConnections(100) // 增加最大连接数.pendingAcquireTimeout(Duration.ofSeconds(30)) // 增加获取连接的等待超时.maxIdleTime(Duration.ofMinutes(8)) // 增加连接最大空闲时间到30分钟.evictInBackground(Duration.ofMinutes(5)) // 后台清理间隔.build();// 配置HTTP客户端HttpClient httpClient = HttpClient.create(connectionProvider)// 连接超时设置.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000) // 增加连接超时到30秒// 读写超时设置.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(8, TimeUnit.MINUTES)) // 增加到30分钟.addHandlerLast(new WriteTimeoutHandler(8, TimeUnit.MINUTES)) // 增加到30分钟)// 禁用自动释放响应内容.disableRetry(true); // 禁用重试// 构建WebClientreturn WebClient.builder().baseUrl("http://127.0.0.1:11434").clientConnector(new ReactorClientHttpConnector(httpClient)).codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) // 增加内存大小到16MB.build();}
}

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;@RestController
public class OllamaController {private final WebClient ollamaWebClient;// 修改构造函数,使用配置好的WebClient Beanpublic OllamaController(WebClient efficientOllamaWebClient) {this.ollamaWebClient = efficientOllamaWebClient;}@PostMapping(value = "/api/model/generate", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)// 关键:返回类型设为APPLICATION_STREAM_JSON_VALUE,而非TEXT_EVENT_STREAM_VALUEpublic Flux<String> streamOllamaReactiveGenerate(@RequestBody String requestBody) {return Mono.just(requestBody).flatMapMany(body ->ollamaWebClient.post().uri("/api/generate").contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(body)).retrieve().bodyToFlux(String.class) // 直接处理为字符串流.onErrorContinue((throwable, o) -> {System.err.println("Error in stream: " + throwable.getMessage());throwable.printStackTrace();}).map(line -> {// 关键修复:移除SSE的data:前缀(如果存在)if (line.startsWith("data:")) {line = line.substring("data:".length()).trim();}System.out.println("line: " + line);return line;}).filter(line -> !line.isEmpty()) // 过滤空行).onErrorContinue((throwable, o) -> {System.err.println("Error in outer stream: " + throwable.getMessage());throwable.printStackTrace();});}@PostMapping(value = "/api/model/chat", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)// 关键:返回类型设为APPLICATION_STREAM_JSON_VALUE,而非TEXT_EVENT_STREAM_VALUEpublic Flux<String> streamOllamaReactiveChat(@RequestBody String requestBody) {return Mono.just(requestBody).flatMapMany(body ->ollamaWebClient.post().uri("/api/chat").contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(body)).retrieve().bodyToFlux(String.class) // 直接处理为字符串流.onErrorContinue((throwable, o) -> {System.err.println("Error in stream: " + throwable.getMessage());throwable.printStackTrace();}).map(line -> {// 关键修复:移除SSE的data:前缀(如果存在)if (line.startsWith("data:")) {line = line.substring("data:".length()).trim();}System.out.println("line: " + line);return line;}).filter(line -> !line.isEmpty()) // 过滤空行).onErrorContinue((throwable, o) -> {System.err.println("Error in outer stream: " + throwable.getMessage());throwable.printStackTrace();});}
}
3.前端h5+js

以下前端代码存在部分错误,gpt快速生成的,仅作为案例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ollama Chat Web</title>
<style>
body {background-color: #f7f9fb;font-family: "Segoe UI", "Microsoft YaHei", Arial, sans-serif;margin: 0;display: flex;flex-direction: column;height: 100vh;
}
header {background-color: #1e88e5;color: white;padding: 10px 20px;display: flex;justify-content: space-between;align-items: center;box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
header .options {display: flex;align-items: center;gap: 12px;
}
header select, header input[type="checkbox"] {padding: 5px;border-radius: 6px;border: none;
}
#chat {flex: 1;overflow-y: auto;padding: 15px;
}
.message {margin: 10px 0;padding: 10px 14px;border-radius: 12px;max-width: 80%;word-wrap: break-word;white-space: pre-wrap;box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.user {background-color: #d1e7ff;align-self: flex-end;margin-left: auto;
}
.bot {background-color: #ffffff;border: 1px solid #ddd;
}
.think {background-color: #f0f0f0;color: #555;font-style: italic;border-left: 4px solid #aaa;margin: 6px 0 6px 20px;padding: 6px 10px;border-radius: 8px;max-width: 75%;white-space: pre-wrap;
}
#input-area {display: flex;padding: 10px;border-top: 1px solid #ddd;background-color: white;
}
#messageInput {flex: 1;padding: 10px;border-radius: 8px;border: 1px solid #ccc;font-size: 15px;font-family: "Segoe UI", "Microsoft YaHei", Arial, sans-serif;
}
#sendBtn {margin-left: 10px;padding: 10px 20px;background-color: #1e88e5;color: white;border: none;border-radius: 8px;cursor: pointer;transition: background-color 0.2s;
}
#sendBtn:hover {background-color: #1565c0;
}
#sendBtn:disabled {background-color: #90caf9;cursor: not-allowed;
}
.loading-indicator {display: inline-block;width: 16px;height: 16px;border: 3px solid rgba(255,255,255,.3);border-radius: 50%;border-top-color: white;animation: spin 1s ease-in-out infinite;
}
@keyframes spin {to { transform: rotate(360deg); }
}
.status-bar {font-size: 12px;color: #666;padding: 5px 15px;border-top: 1px solid #eee;
}
</style>
</head>
<body><header><h3>Ollama Chat Web</h3><div class="options"><label>模型:<select id="modelSelect"><option value="deepseek-r1:1.5b">deepseek-r1:1.5b</option><option value="deepseek-no-thinking">deepseek-no-thinking</option></select></label><label><input type="checkbox" id="dialogueMode" /> 连续对话</label></div>
</header><div id="chat"></div><div class="status-bar" id="statusBar">就绪</div><div id="input-area"><input id="messageInput" placeholder="输入消息..." /><button id="sendBtn"><span id="sendBtnText">发送</span><span class="loading-indicator" style="display:none;"></span></button>
</div><script>
const API_PROXY = "http://10.100.0.106:18089"; // 基础地址分离,方便拼接接口
let chatHistory = [];
let isProcessing = false;
let statusRestored = false;// 滚动到底部
function scrollToBottom() {const chat = document.getElementById("chat");chat.scrollTop = chat.scrollHeight;
}// 更新状态
function updateStatus(text) {document.getElementById("statusBar").textContent = text;
}// 添加消息:返回消息容器,方便后续插入思考块
function appendMessage(role, text, type = "bot") {const chat = document.getElementById("chat");const div = document.createElement("div");div.classList.add("message", type);div.textContent = text;chat.appendChild(div);scrollToBottom();return div; // 返回消息容器,用于插入思考块
}// 创建思考块:改为作为botDiv子元素,确保样式生效
function createThinkBlock() {const thinkDiv = document.createElement("div");thinkDiv.classList.add("think");thinkDiv.textContent = "";thinkDiv.style.marginTop = "8px"; // 增加顶部间距,优化显示return thinkDiv;
}// 构建请求体:按接口类型区分参数
function buildRequest(model, text, isDialogue) {const baseParams = { model: model,  // 模型参数通用stream: true   // 流式请求通用};if (isDialogue) {// 多次聊天(chat):用messages传递历史+当前消息,无promptreturn {...baseParams,messages: [...chatHistory, { role: "user", content: text }]};} else {// 单次聊天(generate):用prompt传递当前消息,无messagesreturn {...baseParams,prompt: text};}
}// 实时更新文本
function updateText(element, newText) {if (element.textContent !== newText) {element.textContent = newText;scrollToBottom();}
}// 解码HTML实体
function decodeHtmlEntities(text) {console.log("解码前:", text); // 调试信息if (typeof text !== 'string') {console.log("文本不是字符串类型:", typeof text); // 调试信息return '';}// 先尝试解码HTML实体let decoded = text.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g, '"').replace(/&#39;/g, "'");// 再处理Unicode转义序列decoded = decoded.replace(/\\u003c/g, '<').replace(/\\u003e/g, '>').replace(/\\n/g, '\n');// 处理多个换行符decoded = decoded.replace(/\n+/g, '\n');console.log("解码后:", decoded); // 调试信息return decoded;
}// 统一恢复UI状态
function restoreUIStatus(isSuccess = true, errorMsg = "") {if (statusRestored) return;const sendBtn = document.getElementById("sendBtn");const sendBtnText = document.getElementById("sendBtnText");const loadingIndicator = document.querySelector(".loading-indicator");sendBtn.disabled = false;sendBtnText.style.display = "inline";loadingIndicator.style.display = "none";statusRestored = true;isProcessing = false;updateStatus(isSuccess ? "处理完成" : `错误: ${errorMsg}`);
}// 发送消息:区分接口地址
async function sendMessage() {if (isProcessing) return;statusRestored = false;isProcessing = true;const input = document.getElementById("messageInput");const text = input.value.trim();if (!text) return alert("请输入消息内容");// 显示加载状态const sendBtn = document.getElementById("sendBtn");const sendBtnText = document.getElementById("sendBtnText");const loadingIndicator = document.querySelector(".loading-indicator");sendBtn.disabled = true;sendBtnText.style.display = "none";loadingIndicator.style.display = "inline-block";updateStatus("正在处理...");const model = document.getElementById("modelSelect").value;const isDialogue = document.getElementById("dialogueMode").checked;// 1. 区分接口地址:单次用generate,多次用chatconst apiUrl = isDialogue ? `${API_PROXY}/api/model/chat`    // 多次聊天接口: `${API_PROXY}/api/model/generate`; // 单次聊天接口// 2. 构建对应参数const requestBody = buildRequest(model, text, isDialogue);// 添加用户消息appendMessage("user", text, "user");input.value = "";// 准备bot容器const botDiv = appendMessage("bot", "");let thinkDiv = null;let fullAnswer = "";let jsonBuffer = "";const timeoutTimer = setTimeout(() => {console.warn("超时未收到响应,自动恢复状态");restoreUIStatus(true, "响应超时,已自动完成");}, 30000);try {// 发送请求const response = await fetch(apiUrl, {method: "POST",headers: { "Content-Type": "application/json;charset=utf-8","Accept": "application/stream+json" },body: JSON.stringify(requestBody)});if (!response.ok) {const errorText = await response.text().catch(() => "未知错误");throw new Error(`[${response.status}] ${errorText}`);}// 处理流式响应const reader = response.body.getReader();const decoder = new TextDecoder("utf-8");while (true) {const { done, value } = await reader.read();if (done) {clearTimeout(timeoutTimer);// 处理剩余JSONif (jsonBuffer.trim()) {tryParseJson(jsonBuffer, botDiv, thinkDiv, model, (content) => fullAnswer += content);}restoreUIStatus(true);break;}jsonBuffer += decoder.decode(value, { stream: true });let jsonEndIndex;while ((jsonEndIndex = jsonBuffer.indexOf('}')) !== -1) {const jsonStartIndex = jsonBuffer.lastIndexOf('{', jsonEndIndex);if (jsonStartIndex === -1) {jsonBuffer = jsonBuffer.substring(jsonEndIndex + 1);continue;}const fullJson = jsonBuffer.substring(jsonStartIndex, jsonEndIndex + 1);jsonBuffer = jsonBuffer.substring(jsonEndIndex + 1);// 修复:传递当前选中的模型,用于判断是否清理思考块const parseResult = tryParseJson(fullJson, botDiv, thinkDiv, model, (content) => {fullAnswer += content;});thinkDiv = parseResult.thinkDiv;if (parseResult.isDone) {clearTimeout(timeoutTimer);restoreUIStatus(true);}}}// 更新连续对话历史(仅多次聊天模式)if (isDialogue && fullAnswer) {chatHistory.push({ role: "user", content: text });chatHistory.push({ role: "assistant", content: fullAnswer });}} catch (e) {clearTimeout(timeoutTimer);console.error("请求错误:", e);updateText(botDiv, `❌ 错误: ${e.message}`);restoreUIStatus(false, e.message);}
}/*** 增强版JSON解析:只处理内容显示*/
function tryParseJson(jsonStr, botDiv, thinkDiv, model, appendAnswer) {let isDone = false;try {const data = JSON.parse(jsonStr);console.log("收到数据:", data);  // 调试信息// 1. 处理结束标记if (data.done === true) {isDone = true;}// 2. 处理回答内容:支持多种格式let responseContent = "";// 格式1: generate接口 - 顶层response字段if (data.response !== undefined) {responseContent = data.response;console.log("单次对话内容:", responseContent);  // 调试信息} // 格式2: chat接口 - 顶层content字段(根据你的调试信息)else if (data.content !== undefined) {responseContent = data.content;console.log("多次对话内容(顶层):", responseContent);  // 调试信息}// 格式3: chat接口 - message.content字段(之前的预期格式)else if (data.message && data.message.content !== undefined) {responseContent = data.message.content;console.log("多次对话内容(嵌套):", responseContent);  // 调试信息} else {console.log("未找到内容字段,完整数据:", data);  // 调试信息}console.log("准备解码的内容:", responseContent);  // 调试信息// 3. 更新内容显示if (responseContent !== undefined) {const decodedContent = decodeHtmlEntities(responseContent);console.log("解码后内容:", decodedContent);  // 调试信息if (decodedContent || responseContent) {  // 即使解码后为空也尝试显示原始内容appendAnswer(decodedContent || responseContent);updateText(botDiv, botDiv.textContent + (decodedContent || responseContent));console.log("更新显示内容:", botDiv.textContent);  // 调试信息}}} catch (e) {console.warn("解析JSON失败,跳过:", e.message, "内容:", jsonStr);}return { thinkDiv, isDone };
}// 事件监听
document.getElementById("sendBtn").addEventListener("click", sendMessage);
document.getElementById("messageInput").addEventListener("keydown", e => {if (e.key === "Enter" && !e.shiftKey) {e.preventDefault();sendMessage();}
});document.getElementById("dialogueMode").addEventListener("change", function() {updateStatus(this.checked ? "已切换到连续对话模式" : "已切换到单次对话模式");
});
</script>
</body>
</html>

运行效果:

后端终端会实时打印模型输出内容,就像使用 ChatGPT 一样逐字生成。
在这里插入图片描述
前端调用:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


🧩 七、常见问题汇总

问题原因解决方案
后端流式返回一段时间后自动停止WebClientConfig中设置的时间过短/本地电脑没有GPU,模型推理很慢增大WebClientConfig中的对时间的配置
API 无响应服务未启动运行 ollama serve &

http://www.dtcms.com/a/553747.html

相关文章:

  • 向华为学习——53页华为制造行业数字化转型工业互联网智能制造解决方案【附全文阅读】
  • 基于电鱼 ARM 工控机的煤矿主控系统高可靠运行方案——让井下控制系统告别“死机与重启”
  • 顶尖网站建设国内大宗商品交易平台有哪些
  • 用langchain搭建简单agent
  • 在 Windows 11 中安装 VirtualBox 7.2.4
  • 【开题答辩全过程】以 基于Java的社交健身系统的设计与实现为例,包含答辩的问题和答案
  • Ubuntu20.04升级autoconf
  • 网站名注册最佳商城ui网站设计
  • R包kuenm和ENMeval--你用对了吗?
  • 接口自动化测试项目框架详解
  • 临安网站建设海口网红
  • 10.string(上)
  • 集团公司手机站网站报送举报网站建设情况
  • 【Spring Boot】Spring AOP动态代理,以及静态
  • 使用Requests和正则表达式实现网络小说爬取技术解析
  • spine动画监听动作播放完成重复执行
  • ui设计网站开发乡村建设的网站
  • 最新版 dify 如何离线安装插件
  • html网站的直播怎么做绵阳个人网站建设
  • 苯乙烯自由基聚合与丙交酯开环聚合的MATLAB模拟
  • 从一到无穷大 #53 Beyond TSDB Query performance: Homomorphic Compression
  • 张掖建设网站眉山市建设局网站
  • Android和springboot的后端json数据库mysql传送
  • 旅游网站系统商标购买网商标
  • 好用的 display: flow-root
  • 做路牌的网站深圳做外贸网站公司
  • C++笔记(面向对象)多重继承 菱形继承
  • 淘宝商品详情 API(taobao.item.get)从 0 到 1:申请流程、核心参数与首次调用实战
  • 大连市建设部网站官网权威的网站建设公司
  • 【Day 83】虚拟化-openstack