从 Java 开发到 AI 工程师:我的大模型入坑指南

3 阅读12分钟

作为一个写了 7 年 Java 的后端开发,我原本以为 AI 就是调个 API 的事儿。直到我真的动手做了个智能质检系统,才发现坑比 Spring 的注解还多。这篇文章记录了我从"Hello World"到能跟老板吹"我们用了 RAG 架构"的全过程。看完你可能还是不会训练大模型,但至少知道怎么让它不胡说八道了。


一、事情的起因:老板说我们要搞 AI

事情是这样的。

某天晨会,老板突然宣布:"兄弟们,AI 是大趋势,我们也要搞!"

我内心 OS:又来。上次这么说还是 2019 年搞区块链,最后做了个内部积分系统,现在还在跑 cron 任务发积分。

但这次不一样。老板是认真的,而且预算到位了。

于是,我这个写 CRUD 起家的 Java 开发,被推到了 AI 项目第一线。

我的 AI 知识储备当时是这样的

  • 知道 GPT 很火

  • 知道 ChatGPT 能写代码(但我不用,怕它把我卖了)

  • 知道"transformer"是个深度学习模型(和 Java 的 Transformer 框架没关系)

    就这,敢接项目?

    嗯,接了。毕竟工资到位,玻璃心碎


二、第一关:Transformer 到底是什么鬼

2.1 面试时的我

面试官:"请讲讲 Transformer 的原理。"

我(自信满满):"Transformer 是 Spring 的一个模块,用于..."

面试官:"我说的是深度学习那个 Transformer。"

我:"..."

那一刻,我感受到了 35 岁危机的预兆。

2.2 恶补 Transformer

Transformer 架构是 Google 2017 年提出的论文《Attention Is All You Need》的核心。

论文标题翻译成人话:别搞那些复杂的 RNN、LSTM 了,注意力机制就够了。

核心组件有三个

(1)Self-Attention(自注意力机制)

作用:让模型在处理每个词的时候,能"看"整句话,判断哪些词跟当前词关系最大。

例子

"小明把踢进了球门,因为太猛了"

当模型处理"它"的时候,Self-Attention 会计算:

  • "它" ↔ "球" → 关联度高 ✅

  • "它" ↔ "小明" → 关联度低

  • "它" ↔ "球门" → 关联度低

    代码理解版(伪代码,别抄):

# Self-Attention 简化版
def self_attention(query, key, value):
    # 计算相似度
    scores = query @ key.T / sqrt(d_k)
    # 归一化
    weights = softmax(scores)
    # 加权求和
    output = weights @ value
    return output

人话总结:就是让每个词跟句子里所有词"握手",握得紧的就是相关词。

(2)Multi-Head Attention(多头注意力)

为什么需要:单个 Self-Attention 只能捕捉一种关系,但语言里关系是多维的。

类比

  • 一个人读书只看字面意思

  • 8 个人同时读——一个看语法、一个看逻辑、一个看情感……把 8 个人的发现合在一起,理解就更全面

    代码(还是伪代码):

# Multi-Head = 多个 Self-Attention 并行
def multi_head_attention(q, k, v, num_heads=8):
    heads = []
    for i in range(num_heads):
        # 每个头学习不同的注意力模式
        head_i = self_attention(q_i, k_i, v_i)
        heads.append(head_i)
    # 把所有头的结果拼起来
    return concat(heads) @ W_o

(3)位置编码(Positional Encoding)

问题:Transformer 是并行处理的,天然丢失了词的顺序。

没有位置编码的后果

"狗咬了人" 和 "人咬了狗" → 模型觉得一样

解决方案:给每个词加上位置信息(用正弦/余弦函数生成)。

# 位置编码简化版
PE(pos, 2i)   = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))

人话:就是给每个位置的词生成一个独特的"位置指纹",加到词向量上。


三、第二关:大模型 API 集成

3.1 选哪个模型?

2026 年了,主流大模型有这么几个:

模型优点缺点适合场景
GPT-4o能力强、生态好贵、国内访问不稳定预算充足、海外业务
Claude长文本强、安全API 配额有限文档分析、长文处理
DeepSeek国产、便宜、能力强偶尔抽风国内业务、成本敏感
Qwen(通义千问)中文优化、阿里生态英文稍弱中文场景、阿里云用户

我们的选择:DeepSeek + Qwen 双备份。

原因:便宜,而且国产模型这几年进步真的很大。

3.2 第一行代码:Hello World

// 别笑,Java 调大模型 API 真的就这么简单
public class LlmClient {
    private final HttpClient httpClient = HttpClient.newHttpClient();
    private final String apiKey = System.getenv("DEEPSEEK_API_KEY");
    
    public String chat(String prompt) throws Exception {
        var request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.deepseek.com/v1/chat/completions"))
            .header("Authorization", "Bearer " + apiKey)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString("""
                {
                    "model": "deepseek-chat",
                    "messages": [{"role": "user", "content": "%s"}]
                }
                """.formatted(prompt.replace(""", "\"")))
            .build();
        
        var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        return extractContent(response.body());
    }
}

测试

var client = new LlmClient();
var result = client.chat("你好,请用一句话介绍你自己");
System.out.println(result);
// 输出:你好!我是 DeepSeek,一个人工智能助手...

那一刻,我感觉自己是个 AI 工程师了。

(后来才知道,这只是一切的开始)


四、第三关:Prompt Engineering(提示词工程)

4.1 什么是 Prompt Engineering?

定义:就是怎么跟大模型说话,让它听懂人话

类比

  • 你让实习生干活,说"帮我弄一下那个"vs"把 Q3 销售数据做成 Excel 表格,按地区分组,下班前给我"

  • 后者得到的结果肯定更好

    大模型也一样:你问得越清楚,它回答得越好。

4.2 Zero-Shot vs Few-Shot

Zero-Shot(零样本)

直接问,不给例子:

问题:这句话的情感是正面还是负面?
"这个手机续航太差了,一天充三次"

模型可能回答:负面 ✅(大多数时候能行)

Few-Shot(少样本)

给几个例子再问:

请将用户评价分类为"正面/负面/中性"。
​
评价:"服务态度特别好,下次还来" → 正面
评价:"一般般,没什么特别的" → 中性
评价:"等了一个小时才上菜" → 负面
​
评价:"这个手机续航太差了,一天充三次"

模型回答:负面 ✅(更稳定)

我们的质检系统用的就是 Few-Shot

String fewShotPrompt = """
    请判断以下客服对话是否违规。违规类型包括:辱骂客户、承诺收益、泄露隐私。
    
    示例 1(违规 - 辱骂客户):
    客服:你这个脑子怎么这么笨
    判定:违规
    原因:辱骂客户
    
    示例 2(违规 - 承诺收益):
    客服:这个产品保证年化 20%
    判定:违规
    原因:承诺不当收益
    
    示例 3(合规):
    客服:我帮您查询一下
    判定:合规
    
    现在请判断:
    客服:%s
    判定:
    """.formatted(customerServiceText);

效果:从 70% 准确率提升到 92%。

4.3 CoT(Chain of Thought,思维链)

问题:大模型有时候会"跳步骤",直接给答案,容易错。

CoT 的作用:让它"一步一步想"。

对比

❌ 直接问:

问:一个商店有 23 个苹果,卖出去 7 个,又进货 15 个,还剩多少?
答:31(可能算错)

✅ 用 CoT:

问:一个商店有 23 个苹果,卖出去 7 个,又进货 15 个,还剩多少?
请一步一步思考。

答:
1. 初始:23 个
2. 卖出 7 个:23 - 7 = 16 个
3. 进货 15 个:16 + 15 = 31 个
4. 最终答案:31 个

我们的用法

String cotPrompt = """
    请逐步分析这段客服对话:
    1. 识别客服和客户的发言
    2. 判断是否有违规话术
    3. 如果有,指出具体哪句话违反了哪条规则
    4. 给出风险等级判定(high/medium/low)
    
    对话内容:%s
    """.formatted(dialogText);

五、第四关:RAG(检索增强生成)

5.1 为什么需要 RAG?

问题:大模型有两大硬伤:

  1. 知识过时:训练数据有截止日期,不知道最新信息

  2. 幻觉:会一本正经地胡说八道

    例子

问:2025 年小米汽车 SU7 的销量是多少?
模型:(瞎编一个数字)

RAG 的思路:先"查资料",再"用资料回答"。

类比

  • LLM 单独用 = 考试不让带书,全凭记忆 → 容易瞎写
  • RAG = 开卷考试,先翻书找到相关内容,再组织答案 → 准确得多

5.2 RAG 架构

用户提问
   ↓
① 检索(Retrieval)
   问题 → 向量化 → 去向量数据库里找最相关的文档片段
   ↓
② 增强(Augmented)
   把检索到的原文片段 + 用户问题一起拼成 Prompt
   ↓
③ 生成(Generation)
   LLM 基于真实资料生成准确回答

5.3 向量数据库选型

主流选择

数据库优点缺点适合场景
Milvus开源、功能全、支持多种索引部署复杂、资源消耗大生产环境、大规模数据
FAISSFacebook 出品、性能强需要自己封装、无持久化原型验证、小规模数据
Pinecone托管服务、开箱即用贵、数据出境问题海外业务、预算充足
Chroma轻量、易上手功能相对简单个人项目、小团队

我们的选择:Milvus(数据量大,需要生产级稳定性)

5.4 代码实现

// 向量化 + 检索简化版
public class RagService {
    private final MilvusClient milvusClient;
    private final EmbeddingClient embeddingClient;
    
    // 检索相关文档
    public List<String> retrieve(String query, int topK) {
        // 1. 把问题向量化
        float[] queryVector = embeddingClient.embed(query);
        
        // 2. 去 Milvus 里搜最相似的文档
        var searchParams = SearchParams.newBuilder()
            .withVector(queryVector)
            .withTopK(topK)
            .withMetricType(MetricType.COSINE)
            .build();
        
        var results = milvusClient.search("knowledge_base", searchParams);
        
        // 3. 提取文档内容
        return results.stream()
            .map(r -> r.getEntity().get("content"))
            .toList();
    }
    
    // 生成回答
    public String answer(String query) {
        // 检索相关文档
        var docs = retrieve(query, 3);
        String context = String.join("\n\n", docs);
        
        // 拼成 Prompt
        String prompt = """
            请根据以下资料回答问题。如资料中无相关信息,请回复"未找到"。
            
            资料:
            %s
            
            问题:%s
            
            回答:
            """.formatted(context, query);
        
        return llmClient.chat(prompt);
    }
}

效果:幻觉问题大幅减少,回答有据可查。


六、第五关:AI Agent 与 Function Calling

6.1 什么是 AI Agent?

定义:能让大模型调用工具、执行动作的系统。

类比

  • 普通大模型 = 只能说话的顾问

  • AI Agent = 能说话 + 能动手的助理

    例子

用户:帮我查一下张三的合同条款

普通大模型:抱歉,我没有这个信息。

AI Agent:(调用 query_contract 工具)
          张三的合同条款如下:...

6.2 Function Calling

原理:定义工具函数,让模型在需要时调用。

我们的质检系统用 Function Calling 实现规则引擎与模型协同

// 定义工具函数
List<FunctionDefinition> tools = List.of(
    FunctionDefinition.builder()
        .name("query_customer_policy")
        .description("查询客户合同条款")
        .parameters(JsonSchema.builder()
            .addProperty("customer_id", SchemaType.STRING)
            .required(List.of("customer_id"))
            .build())
        .build(),
    
    FunctionDefinition.builder()
        .name("check_risk_level")
        .description("根据规则引擎判断风险等级")
        .parameters(JsonSchema.builder()
            .addProperty("text", SchemaType.STRING)
            .required(List.of("text"))
            .build())
        .build()
);

// 模型调用
ToolCall toolCall = model.chat(messages, tools);
if (toolCall.getName().equals("query_customer_policy")) {
    String customerId = toolCall.getArgs().get("customer_id");
    Policy policy = policyService.query(customerId);
    // 把结果回填给模型继续分析
    messages.add(Message.of("tool", policy.toJson()));
    var finalAnswer = model.chat(messages, tools);
}

效果:模型不再是"纯聊天",能真正执行业务逻辑。


七、第六关:可观测性与模型评估

7.1 为什么要监控?

问题

  • 模型回答质量怎么评估?

  • 用户反馈不好怎么定位问题?

  • 成本超支了怎么优化?

    答案:监控、监控、还是监控。

7.2 LangSmith

LangSmith是 LangChain 推出的大模型可观测性平台。

功能

  • 追踪每次调用(输入、输出、耗时、成本)

  • 评估回答质量(自动打分 + 人工标注)

  • 调试 Prompt(对比不同版本效果)

  • 成本分析(按模型、按功能统计)

    我们没用 LangSmith(预算有限),但自己搞了个简化版:

// 简化的监控埋点
@Component
public class LlmMetrics {
    private final MeterRegistry meterRegistry;
    
    // 记录每次调用
    public void recordCall(String model, String function, double latencyMs, int tokens) {
        meterRegistry.counter("llm.calls.total", 
            "model", model, 
            "function", function).increment();
        
        meterRegistry.timer("llm.latency", 
            "model", model, 
            "function", function).record(latencyMs, TimeUnit.MILLISECONDS);
        
        meterRegistry.summary("llm.tokens.used", 
            "model", model).record(tokens);
    }
    
    // 记录用户反馈
    public void recordFeedback(String callId, int rating, String comment) {
        meterRegistry.gauge("llm.feedback.rating", 
            Tag.of("call_id", callId)).record(rating);
        // 评论存到 ES 方便后续分析
    }
}

配合 Grafana 看板

  • 每日调用量
  • 平均响应时间
  • 用户满意度趋势
  • 成本分布

八、踩坑总结

8.1 坑 1:Token 计费比想象中贵

预期:一天几百块够了吧?

现实:上线第一天,账单 3000+。

原因

  • 没限制最大 Token 数

  • 有些请求被恶意刷

  • 重复调用没缓存

    解决方案

  • 设置 max_tokens 上限

  • 加 Redis 缓存(相同问题直接返回)

  • 限流(单用户 QPS 限制)

8.2 坑 2:模型会"记住"对话历史

问题:多轮对话时,历史消息会累积,Token 越来越多。

解决方案

  • 设置最大历史轮数(如最近 5 轮)
  • 用摘要压缩历史(让模型总结之前的对话)

8.3 坑 3:中文模型对专业术语理解差

问题:金融、法律等专业领域,模型容易理解偏差。

解决方案

  • Few-Shot 里加专业术语解释
  • 关键判断走规则引擎,模型只做辅助

8.4 坑 4:向量检索的"语义相似"不等于"业务相关"

问题:向量相似度高,但业务上可能不相关。

例子

  • 用户问"怎么退款"

  • 检索到"退款流程说明"(相关)✅

  • 也检索到"退款政策历史"(不相关)❌

    解决方案

  • 混合检索:向量 + 关键词(BM25)

  • 加 Reranker 精排


九、给 Java 开发的 AI 入门建议

9.1 学习路线

1 周:调 APIHello World)
第 2 周:Prompt EngineeringZero-ShotFew-ShotCoT)
第 3 周:RAG 架构(向量化 + 检索 + 生成)
第 4 周:Agent + Function Calling5 周:可观测性与优化

9.2 推荐资源

类型资源备注
文档LangChain 官方文档有 Python/JS 版本
课程吴恩达《AI For Everyone》免费,入门友好
实践Hugging Face模型、数据集、Demo
社区Reddit r/MachineLearning跟进最新进展
中文知乎"大模型"话题国内实践案例

9.3 心态建议

  1. 别被术语吓到:Transformer、Attention、Embedding,都是纸老虎
  2. 先跑起来再优化:第一版能跑就行,别追求完美
  3. 承认局限性:大模型不是万能的,该用规则就用规则
  4. 保持学习:这个领域变化太快,一个月不学就落后了

十、结语

从"Transformer 是 Spring 模块"到能跟老板吹"我们用了 RAG 架构",我走了 3 个月。

最大的收获:AI 不是魔法,是工程。

它需要:

  • 清晰的架构设计

  • 严谨的代码实现

  • 持续的监控优化

  • 以及对局限性的清醒认知

    最后送大家一句话

不会被 AI 取代的,是那些会用 AI 的人。

共勉。


进一步阅读