公司动态
一文讲透向量 Embedding:从数学概念到 LangChain4j + Qdrant 实战
“大模型的世界本质上是一场「万物皆可向量」的游戏。 这篇文章带你从零开始把「向量」这个看似抽象的概念一路走到能跑起来的工程代码。一、什么是向量在深度学习的世界里向量是最基础、也是最重要的概念之一。它不仅用来表示数据更贯穿了模型的输入、输出以及内部计算的每一个环节。下面我们从几个角度把它彻底讲明白。1. 基本定义向量本质上是一组有序排列的数字。这些数字被称为向量的「分量」或「元素」。在二维空间里一个点可以用「横坐标 纵坐标」两个数来表示在三维空间里则需要「长、宽、高」三个数更一般地在 n 维空间中一个向量就是n 个实数组成的序列。2. 向量在机器学习中的作用向量几乎撑起了机器学习的半边天特征表示原始数据要先转换成数值形式机器才能处理。这些特征值按顺序排好就成了「特征向量」。模型参数很多算法内部都在学习「权重向量」。比如线性回归就是在找一个最优的权重向量 w让预测值和真实值的误差最小。嵌入层Embedding在 NLP 领域词向量、句向量被用来捕捉文本语义。训练得到的词嵌入能真实反映词语之间的语义关系。3. 向量的运算规则向量支持加法、减法、标量乘法等基础运算还有内积点积、外积叉积等特殊运算。正是这些运算构建起了复杂神经网络的底层骨架。4. 向量化编程为了提升效率工程师往往会用「向量化」技术——一次性对整个数组做运算而不是逐个元素循环处理。这种方式极大加速了计算也让代码更简洁优雅。5. 向量空间模型这是信息检索中的经典方法把文档表示成由词汇项组成的向量每个维度对应一个术语值则反映该术语在文档中的重要程度。于是「文档相似度」就变成了「向量相似度」的计算问题。“一句话总结向量是连接理论与实践的桥梁。理解了向量你就握住了理解现代大模型的钥匙。二、向量的数学本质 向量是既有大小、又有方向的量。在数学中我们通常用「有向线段」来表示它——线段的长度代表大小箭头的指向代表方向。关于向量有几条关键性质值得记住向量只有方向和大小。等长、平行、同向的向量因为大小和方向都一致就是同一个向量也叫相等向量。两个向量相等可以用「」连接。但向量之间没有大于或小于关系不能用「」「」连接。方向相同或相反的向量叫作共线向量也叫平行向量。向量之间可以用「∥」或「⊥」连接。其中「a∥b」表示 a 与 b 共线「a⊥b」表示 a 与 b 所在直线互相垂直。向量a的大小又称长度、模长简称模记作 a。模长是数值而非向量所以可以用「」「」比较大小。长度为 0 的向量叫作零向量。零向量与任意向量平行。长度为 1 个单位的向量叫作单位向量。三、什么是向量化一句话向量化就是把文档、字符等内容转换成一组浮点数组。“下图来源于 Qdrant 官方文档向量检索概述章节。四、实战示例LangChain4j Qdrant 理论讲够了接下来上真代码。我们参考 LangChain4j 官方示例Qdrant Embedding Store Example来跑通整条链路。官方案例环境搭建新建模块配置pom.xmlproject xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdcom.whc/groupId artifactIdlangChain4j-whc/artifactId version1.0-SNAPSHOT/version /parent artifactIdlangchain4j-whc-embedding/artifactId packagingjar/packaging namelangchain4j-whc-embedding/name properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !--langChain4j -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-open-ai/artifactId /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-reactor/artifactId /dependency !-- 阿里百炼平台 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-community-dashscope-spring-boot-starter/artifactId /dependency !--lombok-- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !--hutool-- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.22/version /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-spring-boot-starter/artifactId /dependency !--qdrant相关-- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-qdrant/artifactId version1.5.0-beta11/version /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-embeddings-all-minilm-l6-v2/artifactId version1.5.0-beta11/version /dependency dependency groupIdorg.testcontainers/groupId artifactIdqdrant/artifactId version1.19.6/version /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build/project核心代码含详细注释在官方类的基础上稍作修改并补充了完整注释方便理解每一步在做什么public class QdrantEmbeddingStoreExample { /** * gRPC服务端口配置 * 用于连接向量数据库的gRPC通信端口 */ private static int grpcPort 6334; /** * 集合名称配置 * 指定向量数据库中使用的集合名称 */ private static String collectionName langchain4j-whc; /** * 距离计算方式配置 * 设置向量相似度计算的距离度量方式为余弦距离 */ private static Collections.Distance distance Collections.Distance.Cosine; /** * 向量维度配置 * 指定向量的维度大小为384维 */ private static int dimension 384; /** * 数据库主机地址配置 * 向量数据库服务器的IP地址 */ private static final String HOST 192.168.100.130; /** * 数据库端口配置 * 向量数据库服务的端口号与gRPC端口相同 */ private static final int PORT 6334; /** * 主函数演示了使用Qdrant向量数据库进行文本嵌入存储和相似性搜索的完整流程 * * param args 命令行参数数组 * throws ExecutionException 当异步执行出现异常时抛出 * throws InterruptedException 当线程被中断时抛出 */ public static void main(String[] args) throws ExecutionException, InterruptedException { // 创建Qdrant嵌入存储实例用于存储和检索文本嵌入向量 EmbeddingStoreTextSegment embeddingStore QdrantEmbeddingStore.builder() .host(HOST) .port(PORT) .collectionName(collectionName) .build(); // 创建Qdrant客户端用于与Qdrant服务器进行通信 QdrantClient client new QdrantClient( QdrantGrpcClient.newBuilder(HOST, PORT, false) .build()); // 异步创建集合定义向量的维度和距离计算方式 client .createCollectionAsync( collectionName, Collections.VectorParams.newBuilder().setDistance(distance).setSize(dimension).build()) .get(); // 初始化嵌入模型用于将文本转换为向量表示 EmbeddingModel embeddingModel new AllMiniLmL6V2EmbeddingModel(); // 创建并存储第一个文本段落的嵌入向量 TextSegment segment1 TextSegment.from(Ive been to France twice.); Embedding embedding1 embeddingModel.embed(segment1).content(); embeddingStore.add(embedding1, segment1); // 创建并存储第二个文本段落的嵌入向量 TextSegment segment2 TextSegment.from(New Delhi is the capital of India.); Embedding embedding2 embeddingModel.embed(segment2).content(); embeddingStore.add(embedding2, segment2); // 执行相似性搜索查找与查询文本最相似的文本段落 Embedding queryEmbedding embeddingModel.embed(Did you ever travel abroad?).content(); EmbeddingSearchRequest embeddingSearchRequest EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(1) .build(); ListEmbeddingMatchTextSegment matches embeddingStore.search(embeddingSearchRequest).matches(); EmbeddingMatchTextSegment embeddingMatch matches.get(0); // 输出匹配结果的相似度分数和文本内容 System.out.println(embeddingMatch.score()); System.out.println(embeddingMatch.embedded().text()); }}这里的嵌入模型用的是all-MiniLM-L6-v2。“all-MiniLM-L6-v2是 MiniLM 系列的一个小型语言模型通过「知识蒸馏」技术从更大的模型压缩而来。它的目标是——在保持较高性能的同时尽可能降低计算资源需求非常适合本地和轻量场景。✅ 测试一下代码里把两条英文句子转成了向量并保存下来然后提问哪句话更适合回答Did you ever travel abroad?结果如下0.7378319074630284Ive been to France twice.「我去过法国两次」——完美命中模型准确理解了「出国旅行」的语义。五、接口方式接入阿里百炼向量模型 模型选择这里我们选用阿里云百炼平台的向量模型text-embedding-v3。配置类Slf4jGetterConfigurationpublic class LlmConfig { Value(${ai.dashScope.apiKey}) private String dashScopeApiKey; Value(${ai.dashScope.modelName}) private String dashScopeModelName; Value(${ai.dashScope.baseUrl}) private String dashScopeBaseUrl; Value(${qdrant.host}) private String qdrantHost; Value(${qdrant.port}) private int qdrantPort; Value(${qdrant.collectionName}) private String qdrantCollectionName; /** * 创建EmbeddingModel 向量模型 * * return EmbeddingModel */ Bean public EmbeddingModel embeddingModel() { return OpenAiEmbeddingModel.builder() .apiKey(dashScopeApiKey) .modelName(dashScopeModelName) .baseUrl(dashScopeBaseUrl) .build(); } /** * 创建Qdrant客户端 * * return QdrantClient */ Bean public QdrantClient qdrantClient() { QdrantGrpcClient.Builder grpcClientBuilder QdrantGrpcClient.newBuilder(qdrantHost, qdrantPort, false); return new QdrantClient(grpcClientBuilder.build()); } Bean public EmbeddingStoreTextSegment embeddingStore() { return QdrantEmbeddingStore.builder() .host(qdrantHost) .port(qdrantPort) .collectionName(qdrantCollectionName) .build(); }}YAML 配置port: 9008 servlet: encoding: enabled: true force: true charset: UTF-8spring: application: name: langchain_whc_embeddingai: dashScope: # 配置dashScope apiKey: ${AI_DASHSCOPE_API_KEY} modelName: ${AI_DASHSCOPE_MODEL_NAME} baseUrl: ${AI_DASHSCOPE_BASE_URL}qdrant: host: ${QDRANT_HOST} port: ${QDRANT_PORT} collectionName: ${QDRANT_COLLECTION_NAME}ControllerSlf4jRestControllerRequiredArgsConstructorpublic class EmbeddingController { private final LlmConfig llmConfig; private final EmbeddingModel embeddingModel; private final QdrantClient qdrantClient; private final EmbeddingStoreTextSegment embeddingStore; GetMapping(value /embedding/createCollection) public void createCollection() { var vectorParams Collections.VectorParams.newBuilder() .setDistance(Collections.Distance.Cosine) .setSize(1024) .build(); qdrantClient.createCollectionAsync(llmConfig.getQdrantCollectionName(), vectorParams); }}✅ 测试新增 Collection访问接口http://localhost:9008/embedding/createCollection测试结果成功新增了一个 Collection。✅ 测试新增 Points在 Controller 中增加接口这次我们塞一首自创的词进去/** * 处理GET请求向嵌入存储中添加文本段落的嵌入向量 * * return 添加操作的结果标识符字符串 */ GetMapping(value /embedding/add) public String add() { // 定义《永遇乐・师徒取经》词牌的文本内容作为待处理文本 String prompt 永遇乐・师徒取经 万里西行风沙漫卷云路迢递。玄奘慈眉凝眸西向志比金石厉。 悟空火眼金箍掣处妖魅现形惊悸。笑猪痴、贪眠恋栈也随杖履千里。 沙憎谨肃行囊稳护默默担当行李。九九磨难千般险厄终把真经觅。东归胜果流传千古漫说佛门真谛。 到如今、传奇犹在世人共记。 ; // 将文本内容转换为文本段落对象并添加元数据信息 TextSegment segment TextSegment.from(prompt); segment.metadata().put(author, robot); segment.metadata().put(title, 永遇乐・师徒取经); // 生成文本段落的嵌入向量 Embedding embedding embeddingModel.embed(segment).content(); // 将嵌入向量和文本段落添加到嵌入存储中 String result embeddingStore.add(embedding, segment); log.info(result); return result; }测试效果“你可以多塞几条 points 进去让检索结果更有对比性。✅ 测试查询/** * 处理/embedding/query1路径的GET请求用于查询与写爱情的诗相关的嵌入向量匹配结果 * 该方法不接受参数无返回值 */ GetMapping(value /embedding/query) public void query1() { // 生成查询文本写爱情的诗的嵌入向量 Embedding queryEmbedding embeddingModel.embed(与爱情相关的).content(); // 构建嵌入搜索请求 EmbeddingSearchRequest embeddingSearchRequest EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .build(); // 执行嵌入向量搜索 EmbeddingSearchResultTextSegment searchResult embeddingStore.search(embeddingSearchRequest); // 输出查询结果 searchResult.matches().forEach(match - { log.info(\n匹配度得分---- match.score()); log.info(\nmatch.embedded().text()); }); }测试结果有点意思——排序跟直觉略有出入当然也可以加上过滤条件精确锁定某个标题EmbeddingSearchRequest embeddingSearchRequestEmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).filter(metadataKey(title).isEqualTo(鹧鸪天・别绪)).build();六、写在最后 从「向量是什么」到「用 LangChain4j Qdrant 跑通一整套向量检索」我们走完了从理论到工程的完整闭环理论层向量是有序数字组是大模型理解世界的语言工程层向量化把文本变成浮点数组向量数据库负责高效存储与相似度检索实践层无论是本地的 all-MiniLM-L6-v2还是云端的 text-embedding-v3都能轻松接入。理解了向量你就理解了大模型「思考」的底层方式。剩下的就是动手把它跑起来。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】