大模型基本原理与RAG技术体系入门

10 阅读11分钟

文档说明

本文站在Java后端工程师角度,简单的梳理一下从大模型基本原理RAG(检索增强生成)的流程,结合个人业务场景做具象化类比,带大家入门一下大模型的几个基础知识,内容阅读时长10分钟左右。

一、大模型基本原理

1. 基本概念

大模型(LLM,大语言模型)本质是基于海量数据训练的“下一个词概率预测系统” ,不具备真正的“理解能力”,而是通过万亿级参数学习文字/文本的关联规律,以“逐字预测”的方式生成看似智能的内容。

2. 后端视角架构类比

将大模型拆解为Java后端熟悉的系统模块,对应关系如下:

大模型核心模块后端系统类比核心作用
预训练(Training)系统上线前的全量数据初始化投喂万亿级文本数据(网页、书籍、对话),让模型学习“词/句的搭配规律”,相当于把发票政策、业务规则全量导入系统并初始化配置
Transformer架构系统核心业务逻辑层(Service层)大模型的“骨架”,核心是注意力机制(Attention) —— 像后端代码中“聚焦关键字段解析请求”,只关注上下文里的关键信息(如查发票时关注“发票号码”“开票日期”,忽略无关内容)
词嵌入(Embedding)数据标准化编码(如DTO字段映射、JSON序列化)把非结构化文本(如“数电票试点”)转换成计算机可计算的数字向量,相当于给文本发一个“数字身份证”,体现语义特征
推理(Inference)接口请求处理(Controller→Service→DAO)在线阶段接收用户问题(Prompt),逐字预测下一个最可能的词,拼接成完整回答,相当于调用发票查询接口,按规则拼接结果返回
微调(Fine-tuning)系统定制化开发(针对特定场景做功能优化)用小批量专属数据(如企业发票政策)微调模型,让模型更懂特定业务,相当于给通用发票系统新增“数电票试点专属查询逻辑”

3. 核心工作流程

(1)预训练:离线“定规则”(系统初始化阶段)

  • 过程:将海量文本拆解为“字/词”,通过反向传播算法优化模型参数(百亿级/千亿级参数),让模型掌握“词与词的关联规律”。
  • 类比:你开发发票系统时,先把全量税务政策、发票字段规则、历史问答数据导入数据库,再编写“关键词匹配、逻辑校验”等核心代码,完成系统初始化。
  • 关键:预训练是离线操作,不影响在线业务,核心目标是让模型“看懂”通用语言规律。

(2)推理:在线“接龙回答”(接口调用阶段)

用户输入问题后,模型按以下步骤生成回答:

  1. 文本转向量:将用户问题(如“我们公司是不是数电票试点企业?”)转换成Embedding向量,标准化输入格式;
  2. 注意力聚焦:用Attention机制提取问题核心关键词(“数电票”“试点企业”),忽略无关内容;
  3. 逐字预测:从第一个词开始,基于学习到的规律逐字预测下一个词,直到生成完整回答;
  4. 向量转文本:将预测的数字向量转换为人类可读的文本,返回给用户。
  • 类比:用户调用/checkInvoice试点接口,系统先解析请求参数(转向量),聚焦“数电票”“试点”关键字(注意力机制),再按业务规则拼接查询逻辑(逐字预测),最终返回查询结果。

(3)关键补充:大模型“不理解”的本质

大模型看似“智能”,实则是概率预测精度足够高——它不懂“数电票”是什么、不懂“试点企业”的业务含义,只是通过海量数据学会了“这类问题的回答格式和规律”,和你写的发票系统按代码逻辑执行完全不同。

二、Embedding是什么

1. 基本概念

Embedding(嵌入/词嵌入)是将非结构化数据(文本、图片、语音)转换成计算机可计算、可衡量“相似度”的低维数字向量的技术
对Java后端来说,它是给业务文本(如发票政策、用户问题)生成**“语义数字身份证”**,让系统能通过计算向量相似度,判断“文本意思是否相近”,而非仅靠文字匹配。

2. 业务场景类比

传统文本匹配(Java现有方式)Embedding匹配(大模型方式)核心差异
like %数电票%模糊查询发票政策转向量后计算“向量相似度”查询传统只能匹配“文字一致”,Embedding能匹配“意思一致但文字不同”
问题:“数电票试点怎么查” → 匹配不到“全电发票试点查询方法”问题转向量后,匹配到语义相近的政策文本解决“文字不同但语义相同”的匹配问题

具象化示例

  • 文本1:“数电票试点企业判断规则:登录电子税务局查看开票模块” → Embedding向量:[0.23, -0.56, 1.89, 3.01, ...]
  • 文本2:“全电发票试点查询方法:电子税务局找开票业务入口” → Embedding向量:[0.21, -0.55, 1.90, 2.98, ...]
  • 文本3:“蒸龙虾怎么做” → Embedding向量:[5.88, 2.15, -4.32, 0.77, ...]
  • 结论:文本1和2的向量数值相近(相似度>0.9),语义相近;文本1和3向量差异极大,语义无关。

3. Java后端落地核心(调用+存储+检索)

(1)核心作用

支撑RAG技术(企业级AI应用刚需),让大模型能回答企业私有知识库问题(如公司专属发票政策),而非仅回答通用问题。

(2)代码实操(通义千问Embedding接口)

步骤1:引入依赖
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>dashscope-sdk-java</artifactId>
    <version>2.12.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.48</version>
</dependency>
步骤2:核心代码(文本转向量)
import com.aliyun.dashscope.aigc.embedding.EmbeddingResult;
import com.aliyun.dashscope.aigc.embedding.models.EmbeddingParam;
import com.aliyun.dashscope.aigc.embedding.models.EmbeddingRequest;
import com.aliyun.dashscope.utils.Constants;

public class EmbeddingUtil {
    // 替换为你的通义千问API Key
    private static final String API_KEY = "your-dashscope-api-key";

    /**
     * 文本转Embedding向量
     * @param text 业务文本(如发票政策、用户问题)
     * @return 768维数字向量
     */
    public static double[] textToVector(String text) {
        // 1. 设置API密钥
        System.setProperty(Constants.DASHSCOPE_API_KEY, API_KEY);
        
        // 2. 构建Embedding请求参数
        EmbeddingParam param = EmbeddingParam.builder()
                .model("text-embedding-v1") // 通义千问Embedding模型
                .input(text)
                .build();
        EmbeddingRequest request = EmbeddingRequest.builder()
                .embeddingParam(param)
                .build();
        
        // 3. 调用接口获取向量
        EmbeddingResult result = request.call();
        if (result.isSuccess()) {
            return result.getOutput().getEmbeddings().get(0).getEmbedding();
        } else {
            throw new RuntimeException("Embedding接口调用失败:" + result.getMessage());
        }
    }

    // 测试:发票政策转向量
    public static void main(String[] args) {
        String invoicePolicy = "数电票试点企业判断规则:登录电子税务局,查看是否有开票业务模块,有则为试点企业";
        double[] vector = textToVector(invoicePolicy);
        System.out.println("发票政策Embedding向量:");
        for (double num : vector) {
            System.out.print(num + " ");
        }
    }
}

三、RAG是什么(检索增强生成)

1. 基本概念

RAG(Retrieval-Augmented Generation,检索增强生成)是给大模型加装“私有知识库外挂”的技术架构,核心流程是:先从企业私有知识库中检索匹配内容 → 拼接成新的Prompt → 再让大模型基于该内容生成回答
它彻底解决了大模型的三大核心痛点:知识过期、无私有知识、幻觉风险

2. 为什么企业必须用RAG(发票业务痛点)

  • 痛点1:知识过期。大模型预训练数据截止到固定时间(如2025年),无法回答2026年新出的数电票政策;
  • 痛点2:无私有知识。大模型不知道你公司的专属规则(如“贵公司数电票试点需额外提交财务备案”);
  • 痛点3:幻觉风险。无参考数据时,大模型可能瞎编(如乱说“数电票试点需到税务局线下办理”)。
  • RAG解决方案:从企业知识库中精准匹配真实政策,让大模型“有依据地回答”,避免瞎编。

3. RAG完整工作流程(Java后端视角)

(1)流程图解

flowchart TD
    A[用户提问:我们公司是不是数电票试点企业?] --> B[第一步:检索(Retrieval)]
    B --> C[问题转Embedding向量]
    C --> D[从向量库检索语义最像的知识库文本(公司数电票政策)]
    D --> E[第二步:增强(Augmented)]
    E --> F[拼接Prompt:用户问题 + 知识库文本]
    F --> G[第三步:生成(Generation)]
    G --> H[调用大模型,基于拼接内容生成精准回答]
    H --> I[返回给用户]

(2)分步拆解(结合发票业务)

第一步:检索(Retrieval)——找“回答依据”

核心动作:将用户问题转Embedding向量,在向量数据库中检索语义相似度最高的知识库文本。

  • 你的工作:编写Embedding调用代码、向量库相似度查询代码(核心是计算“向量余弦相似度”)。
  • 示例:用户问“数电票试点怎么查”,向量库检索到匹配文本:“数电票试点企业判断规则:登录电子税务局,查看是否有发票业务-勾选模块,有则为试点企业”。
第二步:增强(Augmented)——给大模型“喂素材”

核心动作:将用户问题 + 检索到的知识库文本拼接成清晰的Prompt,明确要求大模型“基于知识库回答”。

  • 你的工作:编写Prompt拼接逻辑,关键是格式清晰,让大模型明确“参考依据”。
  • 示例拼接Prompt:
请严格基于以下知识库内容回答问题,禁止编造信息:
知识库内容:数电票试点企业判断规则:登录电子税务局,查看是否有发票业务-勾选模块,有则为试点企业。
问题:我们公司是不是数电票试点企业?
第三步:生成(Generation)——大模型“精准回答”

核心动作:调用大模型API,传入拼接后的Prompt,大模型基于知识库内容生成回答,而非瞎猜。

  • 你的工作:编写大模型调用代码,处理超时、重试、异常降级等逻辑。
  • 示例回答:“贵公司可登录电子税务局,查看是否存在‘发票业务-勾选’模块,若存在则为数电票试点企业;若不存在,可联系税务部门申请开通。”

4. Java后端落地RAG核心代码(整合版)

基于前文的Embedding、向量数据库(PGVector)、大模型调用代码,整合RAG核心业务逻辑:

(1)核心依赖(补充PGVector、大模型客户端)

<!-- PGVector依赖(PostgreSQL向量扩展) -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.3</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 大模型客户端(通义千问) -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>dashscope-sdk-java</artifactId>
    <version>2.12.0</version>
</dependency>

(2)向量库存储与检索服务

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.Arrays;

@Service
public class RagKnowledgeService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private EmbeddingUtil embeddingUtil;

    /**
     * 存储知识库文本到PGVector
     * @param content 知识库分片文本
     */
    public void saveKnowledge(String content) {
        // 1. 文本转向量
        double[] vector = embeddingUtil.textToVector(content);
        // 2. 向量转PGVector支持的字符串格式([num1,num2,...])
        String vectorStr = Arrays.toString(vector).replace(" ", "");
        // 3. 插入数据库
        String sql = "INSERT INTO invoice_knowledge (content, embedding) VALUES (?, ?)";
        jdbcTemplate.update(sql, content, vectorStr);
    }

    /**
     * 检索相似知识库文本
     * @param userQuestion 用户问题
     * @return 相似度最高的知识库内容
     */
    public String searchSimilarKnowledge(String userQuestion) {
        // 1. 问题转向量
        double[] questionVector = embeddingUtil.textToVector(userQuestion);
        String questionVectorStr = Arrays.toString(questionVector).replace(" ", "");
        // 2. 余弦相似度查询(PGVector用<->运算符)
        String sql = "SELECT content FROM invoice_knowledge " +
                     "ORDER BY embedding <-> ?::vector LIMIT 3"; // 取Top3,保证信息完整
        return jdbcTemplate.queryForList(sql, new Object[]{questionVectorStr}, String.class)
                .stream()
                .findFirst()
                .orElse("");
    }
}

(3)RAG核心服务(回答生成)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.aliyun.dashscope.aigc.generation.GenerationResult;
import com.aliyun.dashscope.aigc.generation.models.GenerationParam;
import com.aliyun.dashscope.aigc.generation.models.GenerationRequest;
import com.aliyun.dashscope.utils.Constants;

@Service
public class RagAnswerService {
    @Autowired
    private RagKnowledgeService ragKnowledgeService;

    // 大模型API密钥
    private static final String AI_API_KEY = "your-dashscope-api-key";

    /**
     * RAG核心方法:基于知识库回答用户问题
     * @param userQuestion 用户问题
     * @return 精准回答
     */
    public String getAnswer(String userQuestion) {
        // 1. 检索相似知识库内容
        String similarContent = ragKnowledgeService.searchSimilarKnowledge(userQuestion);
        // 2. 构建增强Prompt
        String prompt = buildPrompt(userQuestion, similarContent);
        // 3. 调用大模型生成回答
        return callAIModel(prompt);
    }

    /**
     * 构建RAG增强Prompt
     */
    private String buildPrompt(String question, String knowledge) {
        if (knowledge.isEmpty()) {
            return "请回答以下问题:" + question;
        }
        return "【严格要求】基于以下知识库内容回答问题,禁止编造、超出知识库范围,回答需精准、简洁:\n" +
                "知识库内容:\n" + knowledge + "\n" +
                "用户问题:" + question;
    }

    /**
     * 调用大模型API
     */
    private String callAIModel(String prompt) {
        System.setProperty(Constants.DASHSCOPE_API_KEY, AI_API_KEY);
        // 构建大模型请求参数
        GenerationParam param = GenerationParam.builder()
                .model("qwen-turbo") // 通义千问轻量模型
                .input(prompt)
                .build();
        GenerationRequest request = GenerationRequest.builder()
                .generationParam(param)
                .build();
        // 调用并获取结果
        GenerationResult result = request.call();
        if (result.isSuccess()) {
            return result.get

对于 Java后端 开发者而言,大模型技术应用 并非是一个遥不可及的技术,而是一套可理解、可落地、可复用的工程化架构体系。从大模型 “逐词预测” 的基本原理,到 Embedding 实现文本语义化表示,再到 RAG 构建企业级私有知识库,将这个流程中的细节多掌握掌握,多花点时间研究,当个大模型应用开发还是比较容易的。