前七周一直在学后端基础:Spring Boot、MySQL、Redis、微服务、消息队列、ES、分布式。从第八周开始画风变了——学大模型应用开发。一个 Java 后端程序员为什么要学这个?因为 JD 上开始出现了"熟悉 LLM/Agent/RAG 优先"这条要求。

先装 Ollama:本地跑一个大模型

第一天干的事很简单:装 Ollama,拉 Qwen2.5:7b,跑起来。

Ollama 的安装过程没什么好说的,官网下载 Windows 安装包,双击,装完。然后在 PowerShell 里执行 ollama run qwen2.5:7b,它会自动下载模型(7B 版本大约 4-5GB),下载完直接进入对话界面。

我在对话界面里试了几个问题,感受模型的能力边界:

  • “用 Python 写一个快速排序”——代码写得很好,逻辑清晰
  • “鲁迅和周树人是什么关系”——答对了,“鲁迅就是周树人”
  • “2026年8月12日的新闻头条是什么”——开始编了,训练数据没有这个日期的信息
  • “明朝第13任皇帝的皇后姓什么”——也编了,给了一个看起来像模像样但查无此人的答案

试完心里有数了:常识和代码很稳,实时信息和冷门事实容易编。这就是大模型的"幻觉"问题——模型本质是"预测下一个最可能的词",不是"检索事实"。当训练数据里某个事实出现频率低,模型就按概率编一个看起来合理的答案。

把 Ollama 接进 Spring Boot

装好 Ollama 后,它在本地 localhost:11434 开了一个 HTTP 服务。Spring AI 做的事情就是把这个 HTTP 服务包装成 Java 里好用的接口。

pom.xml 加依赖:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

application.yml 配两行:

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:7b

然后注入 ChatClient,三行代码就能对话:

String response = chatClient.prompt()
    .user("用三句话介绍 Elasticsearch")
    .call()
    .content();

prompt() 设消息,call() 同步等回复,content() 取文本。就这么简单。

但 7B 模型生成 200 字的回复要 5-10 秒,用户对着空白页面干等体验很差。所以做了流式输出。

流式输出:让回复"逐字出现"

ChatGPT 的回复不是一下子全出来的,而是一个字一个字蹦出来的。这个体验叫流式输出,技术上用的是 SSE(Server-Sent Events)。

Spring AI 里改两件事就行:把 .call() 换成 .stream(),接口返回类型改成 Flux<String>,加上 produces = "text/event-stream"

@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestBody ChatRequest request) {
    return chatClient.prompt()
        .user(request.getMessage())
        .stream()
        .content();
}

Flux 是 Spring 响应式编程里的类型,表示"一个会陆续产生多个元素的数据流"。和 List 的区别:List 是所有元素都准备好了才返回,Flux 是有一个推一个。大模型生成文本是逐 token 产生的,用 Flux 正好匹配——每生成一段就推给前端,前端用 EventSourceReadableStream 接收,逐段渲染到页面上。

用 curl 测试:

curl -X POST http://localhost:8080/api/chat/stream \
  -H "Content-Type: application/json" \
  -d '{"message": "用五句话介绍 Elasticsearch"}'

能看到回复一段一段地蹦出来:

data:El
data:astic
data:search
data:是
data:一个
data:基于
data:Lucene
data:的
data:分布式
data:搜索
data:引擎

和 ChatGPT 网页版的体验一样。

Prompt Engineering:怎么"调教"大模型

直接问模型"介绍 Java",它会给一个泛泛的回答。但如果我想要特定格式的回答呢?比如 JSON、比如限定字数、比如只回答图书相关的问题。

这就是 Prompt Engineering——通过设计输入文本,让模型的回答更可控。

学了四种策略:

Zero-shot:直接问,不给示例。适合简单任务。

System Message(角色设定):给模型一个身份和行为规范。

ChatClient chatClient = chatClientBuilder
    .defaultSystem("你是一个专业的图书管理员,只回答图书相关问题。回答控制在100字以内。")
    .build();

加了 System Message 后,模型会聚焦图书领域,回答简短,不相关问题会拒绝。

Few-shot:给 2-3 个示例让模型学格式。

.user("""
    示例1:
    用户:我想学Java并发编程
    输出:{"title": "Java并发编程实战", "author": "Brian Goetz"}
    
    示例2:
    用户:我想了解分布式系统
    输出:{"title": "分布式系统概念与设计", "author": "George Coulouris"}
    
    现在请回答:我想学Elasticsearch
    """)

模型会模仿示例的 JSON 格式返回。原理很简单:模型是"下一个词预测器",给它几个"输入→输出"的示例,它会学习这个模式。

Chain-of-Thought(CoT):让模型"一步步思考"。在 Prompt 里加"请一步步分析",模型会列出推理步骤而不是直接猜答案。对数学题、逻辑推理、代码调试特别有效。

实际开发中最常见的需求是让模型返回 JSON。做法是 System Message + Few-shot 组合,拿到结果后用 Jackson 解析。但模型不是 100% 可靠——偶尔会在 JSON 外面包一层 Markdown 标记,或者多加解释文字。生产环境要加清洗逻辑(正则提取 JSON)和重试机制。

Tool Calling:让模型从"能说话"变成"能干活"

前两天的 ChatClient 只能"说话"。用户问"帮我查一下设备 ID 10086 的状态",模型光靠说话查不到——它没连数据库。

Tool Calling 解决这个问题。模型分析用户意图,自主决定调用哪个工具(你的 Java 方法),拿到结果后用自然语言组织回答。

Spring AI 里用 @Tool 注解标记方法:

@Tool(description = "根据设备ID查询设备当前状态,包括在线状态、温度和最后上报时间。")
public Map<String, Object> getDeviceStatus(
        @ToolParam(description = "设备ID,如 10086") Long deviceId) {
    // 查数据库...
    return Map.of("deviceId", deviceId, "status", "ONLINE", "temperature", 42.5);
}

注册到 ChatClient:

ToolCallbackProvider toolProvider = MethodToolCallbackProvider.builder()
    .toolObjects(deviceTools)
    .build();

ChatClient chatClient = builder
    .defaultToolCallbacks(toolProvider)
    .build();

@Tooldescription@ToolParamdescription 非常重要——模型靠这些文字判断什么时候调用、传什么参数。描述写得越清楚,模型调用得越准。

测试效果:

用户问"10086 号设备现在什么状态",控制台打印 [Tool被调用] getDeviceStatus, deviceId=10086,模型回答"10086 号设备当前在线,温度 42.5 度"。

用户问"A 车间的温度传感器有哪些",模型调 searchDevices("A车间 温度传感器")

用户问"帮我看看 A 车间温度传感器最近的告警情况",模型先调 searchDevices 拿到设备 ID,再调 getDeviceAlarms——自动串联两个工具。

和普通 API 调用的本质区别:传统方式是程序员写死 if-else(if 用户说查设备→调设备接口),Tool Calling 是模型自己判断该调什么。扩展时只需注册新 Tool,模型自动学会用。

RAG:给模型装一个"外挂知识库"

Tool Calling 让模型能调用工具,RAG 让模型能查文档。

大模型有一个根本问题:它只知道训练数据里的东西。你的公司文档、设备手册、内部 FAQ,它不可能知道。问它"你们图书馆有没有 Python 入门书",它要么瞎编一本,要么说不知道。

RAG(检索增强生成)的流程:用户提问 → 从知识库里检索相关文档片段 → 把文档 + 问题一起喂给模型 → 模型基于文档回答。

像给一个没读过公司手册的新员工,在他回答问题之前先帮他翻一下手册里相关的几页,让他"开卷考试"。

四步流程:

第一步:文档准备。 把知识库文档(TXT、PDF、Markdown)读进来。Spring AI 提供了 TextReaderPdfDocumentReader 等。

第二步:文档切分。 文档不能整篇丢给模型——太长了,上下文窗口装不下。切成小块(chunk),一般 300-500 token 一块,相邻块之间重叠 50 token(防止关键信息在切分点被切断)。

第三步:向量化 + 存储。 用 Embedding 模型把每个 chunk 转成向量(一串数字,语义相近的文本向量距离也近),存入向量数据库。Spring AI 自带 SimpleVectorStore(内存版,学习用),生产环境用 Milvus、Qdrant 等。

Ollama 的 embedding 模型需要单独拉:ollama pull nomic-embed-text

第四步:检索 + 生成。 用户提问时,把问题也转成向量,在向量数据库里找距离最近的 Top-3 个 chunk,把这三个 chunk 的文本 + 用户问题拼成 Prompt 发给模型。

// 检索相关文档
List<Document> relevantDocs = vectorStore.similaritySearch(question, 3);

// 拼入 Prompt
String prompt = "请根据以下文档内容回答问题:\n" + context + "\n问题:" + question;

// 调用模型
return chatClient.prompt().user(prompt).call().content();

测试两个问题:

问"设备温度过高怎么处理",模型基于 temperature-alarm.txt 的内容回答,列出了检查散热风扇、检查环境温度、校准传感器、安排检修四个步骤。

问"你们图书馆有没有 Python 入门书",模型回答"根据现有文档无法回答。我这里是设备管理平台的运维助手,没有图书管理相关的信息。“——没有幻觉,因为 Prompt 里说了"文档里没有就说无法回答”。

RAG 和 Tool Calling 的分工:查文档用 RAG,查数据/执行操作用 Tool Calling。实际项目里两者配合——用户问"10086 号设备温度过高怎么处理",Tool Calling 先查设备当前状态(温度 85 度、已持续 10 分钟),RAG 再查温度告警处理手册,模型综合两者给出回答。

这周的整体感受

前七周学的是"怎么把系统搭起来"——Spring Boot、微服务、数据库、消息队列、ES、分布式。第八周学的是"怎么让系统变智能"——大模型对话、Prompt 调教、Tool Calling 让模型能干活、RAG 让模型能查资料。

四个技术架构的层次:

  1. 直接调用chatClient.prompt().user("问题").call().content()——模型自由回答
  2. Prompt 工程:加 System Message、Few-shot、CoT——控制模型的回答风格和格式
  3. Tool Calling:注册 @Tool 方法——模型能调用 Java 代码查数据、执行操作
  4. RAG:文档切分→向量化→检索→生成——模型能查文档知识库

从 1 到 4,模型的能力逐步增强:从"能说话"到"说得对"到"能干活"到"能查资料"。

Java 后端会 AI Agent 的人不多。把 Spring AI 的 ChatClient、Tool Calling、RAG 跑通,面试时说"我用 Spring AI 搭了一个能查设备状态、能查文档知识库的运维助手"——这就是差异化。

下周学 LangChain(Python 生态的 AI 框架),用 Python 系统化地构建完整的 RAG 系统。Java 和 Python 两条线并行,后面整合到项目里。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐