Java自定义程序使用Ollama实现本地ai调用
Ollama 提供 两套核心接口、三种常见输入风格、两种输出模式,你可以按需组合。
一、两套核心接口
-
/api/generate
• 一问一答,无对话历史。
• 输入:单次 prompt,可选参数(temperature、top_p、max_tokens …)。
• 输出:单个 JSON(或 SSE 流式 JSON 行)。 -
/api/chat
(推荐做多轮)
• 支持多轮对话,带messages
数组。
• 输入:{"model": "deepseek-r1:7b","messages": [{"role": "system", "content": "你是助手"},{"role": "user", "content": "今天几号"},{"role": "assistant", "content": "今天是..."},{"role": "user", "content": "明天呢"}] }
• 输出:结构同
/api/generate
,但多了message.role
、message.content
字段。
二、三种常见输入写法
-
JSON 字符串(最原始)
String json = "{\n \"model\": \"deepseek-r1:7b\",\n \"prompt\": \"你好\"\n}";
-
Map/Object → JSON(用 Jackson/Gson 省掉拼接
var body = Map.of("model", "deepseek-r1:7b","prompt", "你好","options", Map.of("temperature", 0.7) ); String json = new ObjectMapper().writeValueAsString(body);
-
流式(SSE)输入
把"stream": true
即可,后面用readLine()
逐条解析。
三、两种输出模式
-
一次性(
"stream": false
){"model":"...","response":"今天...","done":true}
-
流式(
"stream": true
) 服务器返回 多行 JSON:{"model":"...","response":"今"} {"model":"...","response":"天"} {"model":"...","response":"是","done":false} ... {"model":"...","response":"","done":true}
前端/终端可边收边渲染,体验更像 ChatGPT。
四、常用可选字段速查
字段 | 作用示例 |
---|---|
temperature | 0~1,越大越“放飞” |
top_p | 0~1,核采样阈值 |
max_tokens | 限制输出长度 |
num_ctx | 上下文窗口大小(默认 2048) |
keep_alive | 模型驻留时间,如 "5m" 、"1h" |
format | "json" 强制返回 JSON 结构(需模型支持) |
一句话总结
-
/api/generate
单轮;/api/chat
多轮。 -
输入可以是简单 prompt,也可以是带 system/user/assistant 的 messages。
-
输出可选一次性 JSON 或 SSE 流式 JSON。
根据业务场景自由组合即可。
一次性输出:
U28/Ollama.java · 伏琪/java基础语法练习 - 码云 - 开源中国https://gitee.com/fuqiqiqi/test/blob/master/U28/Ollama.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;public class Ollama {public static void main(String[] args) throws Exception {// 传统写法:用转义 + 换行String json = "{\n" +" \"model\": \"deepseek-r1:7b\",\n" +" \"prompt\": \"你知道今天是几月几号吗\",\n" +" \"stream\": false\n" +"}";HttpRequest req = HttpRequest.newBuilder().uri(URI.create("http://localhost:11434/api/generate")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build();HttpClient client = HttpClient.newHttpClient();HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());System.out.println(resp.body());}
}
流式输出:
U28/ChatStreamPure.java · 伏琪/java基础语法练习 - 码云 - 开源中国https://gitee.com/fuqiqiqi/test/blob/master/U28/ChatStreamPure.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;public class ChatStreamPure {private static final String URL = "http://localhost:11434/api/generate";private static final HttpClient CLIENT = HttpClient.newHttpClient();public static void main(String[] args) throws Exception {Scanner in = new Scanner(System.in);while (true) {System.out.print("\n你: ");String user = in.nextLine().strip();if ("bye".equalsIgnoreCase(user)) break;// 手写 JSONString json = String.format("{\"model\":\"deepseek-r1:7b\",\"prompt\":\"%s\",\"stream\":true}",escapeJson(user));HttpRequest req = HttpRequest.newBuilder().uri(URI.create(URL)).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8)).build();// 直接拿到 InputStream 逐行读HttpResponse<java.io.InputStream> resp =CLIENT.send(req, HttpResponse.BodyHandlers.ofInputStream());try (BufferedReader br = new BufferedReader(new InputStreamReader(resp.body(), StandardCharsets.UTF_8))) {br.lines().filter(line -> !line.isBlank()).forEach(line -> {int start = line.indexOf("\"response\":");if (start == -1) return;start += 12;char quote = line.charAt(start - 1);int end = line.indexOf(quote, start);if (end == -1) return;String token = line.substring(start, end).replace("\\n", "\n").replace("\\\"", "\"");System.out.print(token);});}System.out.println();}System.out.println("再见!");}private static String escapeJson(String s) {return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");}
}
我是伏琪,关注订阅号伏琪了解更多。