大模型 Embedding 是把文本转换为向量的一种关键能力,也是知识库问答、语义搜索和 RAG 链路里最常被提到的基础模块。很多开发者第一次接触时,通常会直接调用某个 API 或现成库的 encode(),但结果往往是:向量拿到手了,不知道它代表什么;相似度算出来了,不知道阈值该怎么设;检索效果变差了,也无从排查。要真正理解这些问题,就不能只停留在“会调用”层面,还需要把 Embedding 的底层原理、代码实操、模型选型和工程落地串成一条完整链路去看。这篇文章按照“原理 → 代码 → RAG → 选型 → 排错 → 就业”的顺序展开,帮助读者建立一套可以复用的技术认知。
1. 先看懂文本与大模型之间的“向量化”桥
1.1 自然语言不能直接进矩阵,Embedding 是第一层转换
大模型内部做的是矩阵运算,不能直接处理“拼接字符串”。无论 GPT 类模型还是 BERT 类模型,文本进入网络前都要经历一个固定流程:分词、转 ID、查向量表。以“我爱北京”为例,分词器可能把它切分成“我”“爱”“北京”三个 token,每个 token 对应词表里的一个 ID,比如 1001、1002、1003。大模型第一层有一个可训练的 Embedding 矩阵,矩阵的行数是词表大小,列数是模型的隐藏层维度。模型要做的事情,就是根据 token ID 从这个矩阵里取出一行,当作该 token 的初始向量。
这一步看起来简单,但意义很大。它把离散的、无法比较的字符 ID 映射到了连续的向量空间。映射之后,“苹果”和“香蕉”如果训练数据里经常出现在相似上下文中,它们的向量就会逐渐靠近;而“苹果”和“数据库”可能距离较远。这就是 Embedding 能辅助模型理解语义的基础。
1.2 模型内部 Token Embedding 不一定是“检索用文本向量”
很多刚入门的人会把两个概念混在一起:一个是模型内部的 Token Embedding,另一个是外部语义检索常用的文本向量。前者是某个 token 在模型输入层的向量表示,后者是把一整段句子或文档压缩成一个固定长度向量,用来计算两段文本的相似度。
这两者不一定能直接互换。大模型内部的 Token Embedding 是模型为自身任务训练的,适合作为输入特征,但直接拿最后一层平均池化结果去做相似度检索,效果未必好,因为模型在训练时并没有专门优化“句子对是否相似”。检索场景中的文本向量,通常来自专门训练的 Embedding 模型,例如开源的 BGE、GTE、M3E 等系列。它们会通过相似样本对比、相关性排序等方式优化,使得相关文本在向量空间里更接近。
1.3 为什么说 Embedding 是 RAG 和语义搜索的地基
当我们需要构建大模型知识库问答时,不可能把全部业务文档都塞进上下文里。更常见的方式是:先把文档切片,再用 Embedding 模型把每一切片变成向量,存入向量数据库;用户提问时,把问题也向量化,再去向量库里检索最相关的若干段文档,最后把这些文档拼进提示词,交给大模型生成回答。
这条链路中,Embedding 决定了两件事:第一,哪些文档片段能被正确召回;第二,召回结果是否足够相关。如果 Embedding 效果差,后续大模型即使能力很强,也拿不到正确素材,回答就容易变成“没有上下文的安全废话”或“一本正经的编造”。因此,理解 Embedding 不是纯理论任务,而是所有要做语义搜索和大模型应用的人都绕不开的工程基本功。
2. Embedding 底层原理:从离散符号到上下文相关向量
2.1 One-Hot 编码的问题:稀疏但无语义
要理解 Embedding 的价值,可以从 One-Hot 编码的局限开始。假设词表只有四个词:“苹果”“香蕉”“北京”“上海”,那么“苹果”可以被编码为[1, 0, 0, 0],“香蕉”是[0, 1, 0, 0]。这种表示方法简单,但有两个明显问题:第一,维度会随词表膨胀,真实场景词表几十万时,One-Hot 向量的存储和计算代价很高;第二,任意两个词之间的内积都是 0,模型无法从向量上判断“苹果”和“香蕉”比“苹果”和“北京”更相似。
Embedding 用低维稠密向量代替高维稀疏向量。比如用一个 128 维的向量来表示“苹果”,向量的每一位不再是简单的 0 或 1,而是一个连续浮点数。模型可以通过训练不断调整这些数值,让语义接近的词在向量空间中的分布更接近。
2.2 Word2Vec 时代:让词的向量从上下文里长出来
Word2Vec 是理解词向量的一个重要里程碑。它提出两种训练方式:CBOW 和 Skip-gram。CBOW 是拿目标词周围的词去预测目标词,Skip-gram 是拿目标词去预测它周围的词。核心思想是:如果两个词经常出现在相似上下文里,它们就更可能语义相近。
用这种方式训练后,词向量会呈现出一些可计算的语义关系。典型例子是“国王 - 男人 + 女人 ≈ 女王”。这类性质说明,词向量不只是保存了词汇本身,还隐式保存了一部分语义关系和规律。当然,Word2Vec 得到的向量是静态的,意思是无论“苹果”出现在“苹果手机”还是“我吃了一个苹果”里,它都使用同一个向量。这在处理歧义时会受限。
2.3 Transformer 时代:同一词汇在不同语境中拥有不同向量
从 BERT 开始,文本表示变成了上下文相关。模型输入“苹果手机”和“我吃苹果”时,虽然“苹果”在分词后可能是同一个 token,但在经过多层自注意力计算之后,“苹果”这个位置输出的向量会被上下文信息修改。前一句中的“苹果”会更接近电子产品的语义,后一句中的“苹果”会更接近水果的语义。
这种动态向量能力来自 Transformer 的结构设计。Self-Attention 会计算句子中每两个位置之间的关联权重,然后按权重融合其他位置的向量。因此,某个 token 的最终输出向量不是它自己的独立意义,而是它在当前上下文中的意义。这也回答了一个常见问题:为什么不能只用大模型第一层查表得到的 Token Embedding 做检索?因为那个向量还没有经过上下文融合,不能表达整句话的语义。
2.4 句子向量是怎么训练出来的:对比学习和 Pooling
文本检索需要的是“一句话”或“一段文档”的向量,而不只是某个 token 的向量。开源 Embedding 模型通常采用两类做法:一类是在预训练语言模型之上做 Pooling,例如对最后一层 token 向量取均值;另一类是用对比学习或双塔结构做优化,让相似文本对的向量更近,让不相似文本对的向量更远。
对比学习的正样本构造方式很多。例如,同类意图的问题两两互为相似句;同一条知识库文档的改写句互为相似句;也可以用数据增强获得语义相近但表述不同的样本。负样本则可以从无关文档中随机采样,也可以从难负样本中挖掘,即那些表面相似但实际不相关的文本,用来逼着模型学会真正区分相关性。很多优质中文 Embedding 模型会在训练阶段投入大量工作设计负样本,这也是不同模型检索效果差异巨大的原因之一。
2.5 余弦相似度为什么成了默认选择
拿到两个向量后,判断相似度最常用的是余弦相似度。它计算两个向量夹角的余弦值,公式可以写成cos(A, B) = A·B / (|A| * |B|)。余弦相似度只关注方向,不受向量长度影响。文本语义相似更接近“方向是否一致”,而不是“绝对距离是否接近”,所以它被广泛使用。
如果向量在编码时已经做了 L2 归一化,即每个向量长度都是 1,那么余弦相似度可以退化成直接计算内积,这会带来明显的检索性能提升。因为向量数据库和 FAISS 这类工具可以针对内积设计高效的索引结构,而不用每对向量都做一次除法。使用欧氏距离也常见,但在文本语义检索里,它受向量模长影响更大,需要额外小心;如果要做归一化后的欧氏距离,通常表现为相似度越高距离越近,但阈值含义与余弦不同。
| 相似度度量 | 公式 | 特点 | 典型使用场景 |
|---|---|---|---|
| 余弦相似度 | A·B / ( | A | * |
| 内积 | A·B | 归一化后等价于余弦相似度,计算最快 | FAISS、向量库线上检索 |
| 欧氏距离 | |A-B| | 值越小越相似,但受模长影响大 | 部分聚类算法、图像向量场景 |
3. 最小代码实操:跑通一条本地文本检索链路
3.1 Python 环境和依赖准备
要在本地跑通 Embedding 实操,建议使用 Python 3.9 或更高版本,创建一个独立虚拟环境。最小依赖是sentence-transformers和numpy。如果后面要演示 FAISS 检索,再增加faiss-cpu。
python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate pip install --upgrade pip pip install sentence-transformers numpy faiss-cpufaiss-cpu适合学习和原型验证,生产环境再根据是否有 GPU 选择安装包。安装时如果遇到网络问题,需要先确认是否配置了合适的 PyPI 镜像源。模型下载同理,第一次运行会从模型仓库把模型权重下载到本地缓存,耗时取决于网络情况;也可以提前把模型下载好,放到固定目录后通过SentenceTransformer("/your/model/path")加载。
3.2 加载模型并准备示例数据
下面使用开源中文模型BAAI/bge-small-zh-v1.5做演示。这个模型体积较小,适合本地学习和验证。实际项目中,使用哪个模型要结合语言、输入长度和效果测评来定,不能只看名字。
from sentence_transformers import SentenceTransformer model = SentenceTransformer("BAAI/bge-small-zh-v1.5") docs = [ "RAG系统需要将知识库文档切分后转成向量并存入向量库", "语义检索通过文本向量计算相似度,可以处理表达不同但含义相近的问题", "微调大模型时需要关注数据质量、训练轮数和过拟合问题", "推荐系统经常使用物品向量做相似召回", "向量数据库是大模型外挂记忆的重要组件", ] query = "如何搭建基于向量数据库的知识库问答系统"这里刻意让几条文档在主题上存在重叠但不完全相同,方便观察相似度排名。第 1 条和第 5 条都与“知识库”“向量数据库”相关,第 2 条与“语义检索”相关。问题综合了“向量数据库”和“知识库问答”,预期靠前的文档应是第 1 条和第 5 条。
3.3 文本向量化与余弦相似度排名
在编码时,把normalize_embeddings设为True,可以让所有输出向量长度为 1。这样直接使用内积也能得到余弦相似度,同时便于之后接入 FAISS。为了把原理体现得更明显,下面的代码里先手动实现余弦相似度。
import numpy as np doc_vectors = model.encode(docs, normalize_embeddings=True) query_vector = model.encode([query], normalize_embeddings=True) def cosine_similarity(v1, v2): return float(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))) results = [] for doc, vector in zip(docs, doc_vectors): score = cosine_similarity(query_vector[0], vector) results.append((doc, score)) results.sort(key=lambda item: item[1], reverse=True) for rank, (doc, score) in enumerate(results, 1): print(f"第{rank}名 相似度{score:.4f} {doc}")这里需要理解两个关键点。第一,query_vector本应只编码一个句子,但为了保持输入形状,仍然写成列表[query],所以取第一个向量。第二,normalize_embeddings=True的情况下,np.linalg.norm(v1) * np.linalg.norm(v2)的结果约等于 1,因此这段代码得到的相似度和直接取内积基本一致。保留完整写法是为了帮助读者理解公式来源,并不是性能最优实现。
3.4 用 FAISS 替代手工循环
当文档数量达到几万甚至上百万时,手工遍历所有向量计算相似度是行不通的。FAISS 提供了多种索引结构,其中最基础的IndexFlatIP是暴力内积检索,虽然它没有做特殊的空间切分,但底层使用 BLAS 优化,仍然可以比 Python 循环快很多。由于上面的向量已经做了 L2 归一化,IndexFlatIP计算出的内积就等价于余弦相似度。
import faiss import numpy as np doc_vectors = np.asarray(doc_vectors, dtype=np.float32) query_vector = np.asarray(query_vector, dtype=np.float32) index = faiss.IndexFlatIP(doc_vectors.shape[1]) index.add(doc_vectors) scores, indices = index.search(query_vector, k=2) for rank, (score, idx) in enumerate(zip(scores[0], indices[0]), 1): print(f"第{rank}名 相似度{float(score):.4f} {docs[idx]}")使用 FAISS 时要注意向量类型必须是float32,且索引维度要和向量维度一致。如果执行到这里报TypeError或dimension mismatch,优先检查是否做了np.asarray(..., dtype=np.float32)。
3.5 预期输出与评估方法
一次正常的运行结果会输出类似下面的内容,相似度数值取决于模型和文档内容。
第1名 相似度0.7481 RAG系统需要将知识库文档切分后转成向量并存入向量库 第2名 相似度0.6714 向量数据库是大模型外挂记忆的重要组件 第3名 相似度0.5542 语义检索通过文本向量计算相似度,可以处理表达不同但含义相近的问题这里最有价值的不是具体分数,而是排名是否符合直觉。可以通过调整 query 或替换相近文档,对比不同模型输出。要评估一个 Embedding 方案是否适合业务,不能只看一两个例子,至少要准备一批真实问题,人工标注出每个问题的标准答案文档,再计算召回率或命中率。例如,在 100 个问题中,Top-5 能命中的比例越高,方案越可信。
4. 把 Embedding 接入 RAG:从相似度结果到最终回答
4.1 只有 Embedding 还不够,还要先解决文档切分问题
Embedding 负责把一段文本变成向量,但“一段文本”不是天然存在的。业务文档通常很长,比如 PDF 合同、技术文档、客服话术。直接把整篇文档转成一个向量,检索时只会得到一个粗粒度的答案,无法告诉大模型具体该看哪一段。因此,RAG 项目开始前要设计文档切分策略。
切分策略没有通用标准,但通常有几个方向:按固定字符长度切分、按段落或标题切分、按语义结构切分。固定长度切分时还要设置重叠区域,例如每个 chunk 500 字符,相邻 chunk 重叠 50 字符,避免一个完整句子被硬生生切断。切分过度也不好,太小的 chunk 会导致向量不包含足够上下文,索引体积变大,召回结果碎片化。
4.2 RAG 标准链路里的 Embedding 位于哪个环节
RAG 的完整流程可以拆成索引阶段和查询阶段。索引阶段先把原始文档清洗、切分,用 Embedding 模型生成向量,再把向量写入向量数据库。查询阶段则把用户 query 编码成向量,到向量库召回 Top-K 文档,然后对这些文档做拼接,连同原始问题一起交给大模型。
这个链路中有一个容易被忽视的问题:不同阶段是否使用了同一个 Embedding 模型。如果离线入库用 A 模型,线上查询时误用了 B 模型的向量,两个模型输出空间不一致,检索结果会完全不可用。实际排查故障时,这个问题常被忽略,因为程序并不会报错,只是检索分数异常或召回内容无关。
4.3 搭建本地 RAG 的常见组件与配置思路
本地搭建 RAG 时,除了 Embedding 模型,还需要大模型推理服务和向量数据库。如果只是想验证链路,可以先用轻量级组件:用sentence-transformers生成向量,用 FAISS 或 Chroma 做向量存储,用本地的 GGUF 或 Ollama 部署的大模型做生成。RAGFlow 等开源知识库系统会把文档解析、切分、向量入库、问答编排做成界面化产品,适合项目验证,也方便理解生产环境里的组件边界。
从工程配置看,要注意两个地址:一是 Embedding 服务的地址,二是大模型生成服务的地址。很多开源系统允许在配置文件中分别指定这两个服务,例如把 Embedding 指向本地Ollama的 embedding 模型接口,把大模型指向另一个提供对话接口的本地服务。这样做的好处是职责分离:向量化需要并发处理大量短文本,大模型生成需要长上下文和 GPU 显存,两者资源需求不同,放在同一个服务里容易互相抢占资源。
4.4 Embedding 选择错误会如何影响最终回答质量
如果 Embedding 模型不能很好理解业务术语,检索阶段可能召回无关段落,最终回答质量会大幅下降。比如一个法律知识库,使用通用中文模型可能处理不了大量法条编号和行业黑话。此时方案不是马上微调大模型,而是先评估是否需要微调 Embedding 模型,或者选用更合适的领域 Embedding 模型。
嵌入模型微调需要构建正负样本:正样本是“问题和标准答案文档”,负样本是“问题但与答案不相关的文档”。这类训练数据通常比大模型微调数据更容易准备,但不要在没有评测指标的情况下盲目进行。更稳妥的做法是先做一套小规模检索评测集,对比不同模型的 Recall@5,再决定是换模型、调 chunk 还是做 Embedding 微调。
5. Embedding 模型选型、参数和部署细节
5.1 中文场景常见的模型家族有哪些
在近几年的中文 Embedding 方案中,能看到多个开源系列被广泛讨论,例如 BGE、GTE、M3E 等。它们有的是通用语义表示模型,有的针对中文检索优化。除了开源模型,也有闭源文本 Embedding API 可供选择。选型时要先确认模型许可、最大输入长度、向量维度和维护状态,不要只凭某个榜单或短期热度做决定。
选择模型时,可以按下面的步骤做快速筛查:第一,确认业务文本主要是中文、英文还是混合语言;第二,确认文本平均长度是否会超过模型最大 token 数;第三,用 100 条真实问答做候选模型召回效果对比;第四,评估部署成本和响应时间。这个过程可以沉淀成团队的选型清单,避免每个项目都从零开始讨论。
| 考察项 | 重要程度 | 常见核查方式 |
|---|---|---|
| 语言支持 | 高 | 中英文效果分开测,注意不常见符号 |
| 最大输入长度 | 高 | 查看模型卡,对长文档做切分测试 |
| 向量维度 | 中 | 关系到存储成本和检索性能 |
| 许可证 | 高 | 商用前确认协议是否允许 |
| 部署成本 | 中 | 小模型可 CPU 推理,大模型需要 GPU |
5.2 输入长度、向量维度和参数量决定了技术边界
输入长度决定一段文本最多能包含多少个 token。如果一段文档超过上限,默认行为可能是截断,也就是后半部分信息直接丢失。向量维度则直接影响向量库的存储和检索速度。例如维度 384 和维度 1536 相比,后者单个向量占用的内存更大,在百亿级向量场景中成本差异显著。参数量决定模型表达能力,但不代表效果一定更好,小模型经过良好训练也能在特定业务上超过大模型。
实际业务中不要盲目选择最高维度。可以先选择一个效果达标、维度适中的模型,等数据量和并发量都验证后,再评估是否需要升级。对于已经入库的向量,切换模型维度时必须重建索引,否则向量库会报维度不一致。
5.3 关键参数:batch_size、normalize_embeddings 和 device
使用 SentenceTransformer 编码时,最常调整的几个参数包括batch_size、normalize_embeddings和device。batch_size控制一次编码多少条文本,调大可以提高 GPU 利用率,但显存有限,过大会报 OOM;改为 CPU 推理时,过大的 batch 反而会让单条请求等待更久。normalize_embeddings决定向量是否做 L2 归一化。如果后面用 FAISS 的IndexFlatIP做内积检索,建议开启;如果使用向量数据库且库端默认存储原始向量,也要在代码里保持一致。device可设为"cpu"或"cuda"。生产环境如果使用 GPU,需要额外考虑显存占用量和应用并发;如果只是给内部工具提供接口,CPU 运行小模型也完全可行。
5.4 本地部署和远程 API 如何取舍
本地部署 Embedding 模型的好处是数据不出内网、可控性强、可以按需微调。缺点是运维成本高,需要监控显存、模型版本、接口超时和并发。远程 API 的优势是接入简单、不需要自己维护模型,但必须把业务文本传到外部服务,数据安全需要单独评估。很多企业最终会采用折中方案:通用场景调用开源模型本地部署,特殊语言或领域场景通过微调后部署私有模型。
在部署方式上,可以直接用 FastAPI 包一层/embed接口,也可以使用 Ollama 提供的本地 HTTP 能力。如果只做学习验证,Ollama 会省去很多 Python 依赖问题;如果要做生产级并发控制、监控和版本管理,建议通过专门的模型服务组件统一接入。
6. 实际项目里的常见坑:现象、原因、排查路径
6.1 检索结果看起来相似,但没命中真正想要的答案
一种很典型的失败场景是:相似度分数很高,但返回内容只是措辞相近,并非业务想要的标准答案。这通常不是单一原因造成的,可能是 query 和文档表达方式差异过大,可能是负样本不足导致模型没有学会区分微妙差异,也可能是文档切分导致关键信息被切成两段。
排查时先打印实际送到模型里的 query 和文档文本,看有没有多空格、乱码或错误拼接。再检查模型是否为该文本领域做过针对性训练。如果模型本身没问题,可以用 BM25 等传统关键词召回做对照。BM25 和 Embedding 召回不是互斥关系,很多系统会同时跑两路召回,再合并结果,避免单一方式的盲区。
6.2 文本被截断,长文件末尾信息永远检索不到
如果向量库里的文档包含较长段落,而 Embedding 模型最大长度只有 512 token,那么超出部分会被截断。数据库中留存的实际向量只代表前几百个 token,尾部关键信息没有被编码,自然无法被检索到。
解决思路是控制入库单元长度。可以按章节先切分,再对过长章节做二次切分,并为每段保留标题或摘要前缀。例如每个 chunk 保存“标题 + 原始文本片段”,这样向量既能表达上下文,又不会超过模型长度。生产环境还要在写入前检查 token 数量,而不是只按字符数判断。
6.3 新文档不断进来,旧文档更新后向量索引容易过期
很多知识库的文档不是静态的。当原始文档被修改后,如果只更新业务数据库而不更新向量索引,检索结果就会一直命中旧版本。更隐蔽的问题是删除操作:如果只在向量库中删除旧向量,没处理好对应文档的关联 ID,就容易留下孤儿向量。
工程上建议给每条入库文本记录统一的文档 ID、chunk 序号和内容哈希。内容变更后,先计算哈希,若不一致则重新生成向量并更新索引。这样即使出现数据错乱,也能通过哈希定位。
6.4 Embedding 服务成为高并发瓶颈
当请求量大时,向量化接口往往会成为性能瓶颈,因为 Embedding 模型是深度神经网络,单条请求的处理延迟虽不高,但大量请求同时进来时,如果模型没有批量推理能力,吞吐量会很低。
不要把每一次调用都单独打一次 HTTP 请求。批量操作时,尽量把多条文本合并成一个 batch 再调用模型。对于知识库入库任务,应该设计离线批处理脚本;对于线上查询,可以增加相似 query 的缓存。另外,可以将小 batch 控制在模型服务的max_batch_size以内,观察 GPU 显存和延迟,找到吞吐量最优的并发数。
6.5 排查顺序速查表
| 问题现象 | 先查什么 | 再查什么 | 常见解决方式 |
|---|---|---|---|
| 召回结果不相关 | 输入文本是否有误 | query 是否加了正确前缀 | 清洗 query,按模型卡要求处理 |
| 向量维度报错 | 入库和查询是否用同一模型 | 是否有旧索引残留 | 统一模型版本,重建索引 |
| 长文档信息召不回 | 是否超 max length | chunk 是否有重叠 | 增加切分,加摘要前缀 |
| 效果对比差 | 是否只靠一两个例子 | 有误标注的评测集 | 做 Top5 命中率评估 |
| 接口高延迟 | 是否单条请求多次调用 | 模型是否放在 GPU | 批量推理、增加缓存 |
7. 就业视角:把这些能力转换成面试和项目经验
7.1 哪些岗位会直接考察 Embedding
与 Embedding 关系最直接的岗位通常包括大模型应用工程师、AI 知识库开发工程师、语义搜索算法工程师和 RAG 应用工程师。这些岗位不一定要求从零设计一个全新模型,但普遍要求候选人能理解 Embedding 原理、会调用或部署模型、能搭建语义检索链路,也能够在效果不好时给出排查方案。除了算法岗,后端工程师如果想做向量数据库、模型推理服务,也会遇到 Embedding 相关技术。
从就业角度看,Embedding 并不是一个孤立知识点,而是连接 NLP 基础、Transformer、搜索系统和大模型应用的综合能力。比起只背概念,企业更看重候选人能否把文本、向量、检索、生成这四件事串起来讲清楚。
7.2 面试常见问题与作答重点
面试考察通常在“解释原理”和“解决工程问题”两层之间穿插。初级问题可能是:One-Hot 和 Embedding 有什么区别,为什么文本相似度常用余弦相似度。进阶一点的问题会问:Word2Vec 和 BERT 得到的词向量有什么区别,如何在 RAG 里选择 Embedding 模型,向量维度太大怎么办,召回效果差如何排查。更偏工程的问题则是:索引库如何增量更新,如何在响应时间与召回效果之间做取舍,线上模型版本升级后如何保证向量空间一致。
作答时不要只背概念。讲 Word2Vec 时尽量带出“静态词向量”和“上下文无关”是否适合当前业务;讲 BERT 时强调动态向量依赖上下文;讲 RAG 时主动提出切分、索引、召回、重排、缓存等实践环节。能用自己的项目经历说明“为什么这样选”,比堆术语更可信。
7.3 简历上怎么写:从“调用 API”升级到“效果可控”
很多项目经验会这样写:使用 OpenAI Embedding 接口做过知识库问答。这种描述没有信息量,因为只说明