六维教程

文本嵌入

文本生成能回答问题、写文章,但有些任务不是生成文字,而是理解文字之间的关系。比如判断两句话意思是否相近、从一堆文档里找出和某个问题最相关的那篇。这类任务靠关键词匹配效果差,要用文本嵌入把文字变成向量,再用数学方法算相似度。这篇讲清楚嵌入是什么、Workers AI 怎么调用嵌入模型、怎么计算语义相似度。

什么是文本嵌入

文本嵌入(Text Embedding)是把一段文字映射成一组数字的过程。这组数字叫向量,通常有几百到几千个维度。关键在于,意思相近的文字生成的向量也相近,意思无关的文字向量距离远。

一段文字变成向量的过程

"今天天气很好" → [0.12, -0.34, 0.56, ..., 0.78]  (比如 768 个数字)
"今日气候不错" → [0.11, -0.32, 0.55, ..., 0.77]  (向量很接近)
"我想买台电脑" → [0.89, 0.21, -0.43, ..., 0.05]  (向量差很远)

这和关键词匹配的区别

对比项 关键词匹配 向量嵌入
工作原理 字面是否包含某个词 语义层面的意思是否相近
同义词 匹配不到 能识别为相近
“汽车””轿车” 当成无关词 向量距离近
拼写错误 直接失效 仍能匹配到相近语义
计算方式 字符串包含判断 向量距离或余弦相似度

嵌入是语义搜索、推荐系统、RAG(检索增强生成)的基础。把文档全部转成向量存起来,用户提问时把问题也转成向量,找距离最近的几篇文档就是最相关的结果。

嵌入模型

Workers AI 提供了几个嵌入模型,都来自 BAAI(北京智源人工智能研究院)的 BGE 系列。文本生成模型输出的是文字,嵌入模型输出的是向量,调用方式类似但参数和返回结构不同。

可用的嵌入模型

模型 ID 向量维度 语言支持 特点
@cf/baai/bge-small-en-v1.5 384 英文 最快最省,适合大量数据
@cf/baai/bge-base-en-v1.5 768 英文 精度和速度平衡
@cf/baai/bge-large-en-v1.5 1024 英文 精度最高,速度最慢
@cf/baai/bge-m3 1024 多语言含中文 中文场景首选

选型看两点。语言决定选哪个系列,中文内容用 bge-m3,纯英文按精度需求选 small 或 base。维度影响存储成本和检索速度,维度越高信息越丰富但存储和计算开销越大。

基础嵌入调用

调用嵌入模型传 text 参数,可以传单个字符串,也可以传字符串数组批量处理。

export default {
  async fetch(request, env) {
    const embeddings = await env.AI.run("@cf/baai/bge-m3", {
      text: ["今天天气很好", "我想买台电脑"],
    });

    return Response.json({
      shape: embeddings.shape,
      // 向量太长只展示前 5 个数字
      preview: embeddings.data[0].slice(0, 5),
    });
  },
};

返回结构

{
  "shape": [2, 1024],
  "data": [
    [0.012, -0.034, 0.056, "...共 1024 个数字"],
    [0.089, 0.021, -0.043, "...共 1024 个数字"]
  ]
}

字段说明

字段 含义
shape 向量矩阵的形状,[文本数, 维度数]
data 二维数组,每个元素是一段文本的向量

批量传 text 比循环单条调用效率高,网络往返少,神经元消耗也更省。一次最多建议几十条,太多可能超时。

pooling 参数

BGE 系列模型有个 pooling(池化)参数,决定怎么把模型中间层输出聚合成最终向量。它接受 clsmean 两个值。

const embeddings = await env.AI.run("@cf/baai/bge-base-en-v1.5", {
  text: ["Hello world"],
  pooling: "cls",
});

两种池化方式对比

pooling 值 原理 精度 注意事项
cls 取句首标记的向量 更准确 Cloudflare 推荐用这个
mean 对所有 token 向量求平均 略低 默认值,向后兼容旧版本

这里有个坑。cls 和 mean 产生的向量不兼容,不能混用。如果索引库里的向量是用 mean 生成的,查询时也必须用 mean,否则相似度计算全是错的。新建项目直接用 cls,精度更好。老项目迁移要重新生成所有向量。

相似度计算

拿到向量后,怎么判断两段文字意思近不近。最常用的是余弦相似度(Cosine Similarity),衡量两个向量方向的夹角。夹角越小越相似。

余弦相似度公式

cos(A, B) = (A·B) / (|A| × |B|)

A·B 是两个向量的点积,就是对应位置相乘再求和。|A| 和 |B| 是各自的模长。结果范围是 -1 到 1,越接近 1 表示越相似。

三种相似度算法对比

算法 计算方式 适合场景 是否受向量长度影响
余弦相似度 向量夹角 语义搜索、文本匹配
点积 对应位相乘求和 已归一化的向量
欧氏距离 空间直线距离 聚类、异常检测

嵌入模型输出的向量通常没归一化,所以用余弦相似度最稳妥。如果预先把向量归一化(除以模长),点积的结果就等于余弦相似度,计算更快。

实现相似度计算

在 Worker 里写一个余弦相似度函数,比较两段文本的语义接近程度。

function cosineSimilarity(a, b) {
  let dot = 0;
  let normA = 0;
  let normB = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    normA += a[i] * a[i];
    normB += b[i] * b[i];
  }
  return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

export default {
  async fetch(request, env) {
    const { text1, text2 } = await request.json();

    const embeddings = await env.AI.run("@cf/baai/bge-m3", {
      text: [text1, text2],
      pooling: "cls",
    });

    const score = cosineSimilarity(embeddings.data[0], embeddings.data[1]);

    return Response.json({
      text1,
      text2,
      similarity: score,
    });
  },
};

测试几组文本能直观看到效果

文本 A 文本 B 相似度(参考值)
今天天气很好 今日气候不错 约 0.85
今天天气很好 这家餐厅很好吃 约 0.55
今天天气很好 服务器配置文件 约 0.25

注意相似度是相对值,不是绝对阈值。不同模型、不同 pooling 方式算出来的数值范围不一样。实际应用要先用自己的数据测一批,定一个合适的阈值,比如 0.7 以上算相关。

语义搜索示例

嵌入最典型的用途是语义搜索。把一批文档预先转成向量存起来,用户搜索时把查询也转成向量,找相似度最高的几篇返回。

// 假设这是预先存好的文档向量,实际项目存到 Vectorize 或 D1
const DOCS = [
  { id: 1, text: "Workers 是 Cloudflare 的边缘计算服务", vector: [] },
  { id: 2, text: "R2 是 Cloudflare 的对象存储", vector: [] },
  { id: 3, text: "D1 是 Cloudflare 的 SQLite 数据库", vector: [] },
];

export default {
  async fetch(request, env) {
    const { query } = await request.json();

    // 把查询转成向量
    const queryEmbedding = await env.AI.run("@cf/baai/bge-m3", {
      text: [query],
      pooling: "cls",
    });
    const queryVector = queryEmbedding.data[0];

    // 算每篇文档和查询的相似度
    const results = DOCS
      .map((doc) => ({
        id: doc.id,
        text: doc.text,
        score: cosineSimilarity(queryVector, doc.vector),
      }))
      .sort((a, b) => b.score - a.score);

    return Response.json({ query, results });
  },
};

实际项目中文档向量要存到专门的向量数据库,Cloudflare 自己有 Vectorize(Cloudflare 的向量数据库服务)可以做这件事。纯计算几百篇文档在 Worker 里算还能接受,上万篇就必须用向量数据库的索引能力了。

小结

文本嵌入把文字变成向量,让机器能从语义层面衡量文本的相似程度。Workers AI 提供 BGE 系列嵌入模型,中文用 bge-m3,英文按精度需求选 small 或 base。调用方式和文本生成类似,传 text 数组批量转换更高效。拿到向量后用余弦相似度算接近程度,配合向量数据库就能搭语义搜索和推荐系统。下一篇讲结构化输出,让模型按指定 JSON 格式返回数据,方便程序直接消费。

上一篇 流式输出

下一篇 结构化输出

上一篇
流式输出
下一篇
结构化输出