LlamaIndex 中 Together Embedding 集成的完整指南:TogetherEmbedding 的初始化、API 调用与异步批处理原理
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
本篇技术指南以 LlamaIndex 官方 API 参考文档中llama_index.embeddings.together(即TogetherEmbedding)条目为核心,结合该开源仓库中llama-index-embeddings-together集成包的源码实现、单元测试与 Notebook 示例,系统讲解如何在 LlamaIndex 应用中使用 Together AI 的嵌入模型完成文本与查询向量化。读完本文,你将掌握TogetherEmbedding的安装方式、参数配置、同步/异步调用方法、底层 HTTP 请求结构与限流重试机制,以及如何将其作为全局嵌入模型接入向量索引构建 RAG 应用。
集成包概览:Together Embedding 在 LlamaIndex 中的位置
在 llama_index 仓库中,Together 嵌入能力的实现位于集成子仓库 llama-index-integrations/embeddings/llama-index-embeddings-together/,由 pyproject.toml 定义其包元数据:
- 包名:
llama-index-embeddings-together,版本0.5.0; - 运行依赖:
llama-index-core>=0.13.0,<0.15; - 解释器要求:
requires-python = ">=3.10,<4.0"; - 导入路径:
llama_index.embeddings.together(在[tool.llamahub]中声明为import_path)。
因此,安装命令对应为:
pip install llama-index-embeddings-together包内模块结构清晰:入口模块 llama_index/embeddings/together/init.py 只做了一件事——从base.py导出公开类,__all__ = ["TogetherEmbedding"],同时使用 Hatchling 构建后端打包含llama_index/目录。也就是说,整个集成的全部业务逻辑都收敛在唯一的核心类TogetherEmbedding中,开发者只需从llama_index.embeddings.together导入这一个符号即可。
类继承关系与核心字段:TogetherEmbedding 的设计骨架
TogetherEmbedding定义于 base.py,直接继承自 LlamaIndex Core 的抽象嵌入基类BaseEmbedding(位于 llama-index-core/llama_index/core/base/embeddings/base.py)。作为BaseEmbedding的子类,它自动获得 LlamaIndex 嵌入模型体系的全部公共能力,包括model_name、embed_batch_size、callback_manager、num_workers、可选的embeddings_cache与rate_limiter等 Pydantic 字段,以及以@dispatcher.span装饰、可被观测/回调系统追踪的公开入口方法(如get_query_embedding等)。
TogetherEmbedding自身声明了两个 Pydantic 字段,它们是理解其行为的钥匙:
| 字段 | 默认值 | 语义 |
|---|---|---|
api_base | "https://api.together.xyz/v1" | Together API 的基础 URL,所有请求都在此地址上拼接/embeddings端点。 |
api_key | "" | 访问 Together API 的密钥。若未显式传入,则在__init__中回退读取环境变量TOGETHER_API_KEY。 |
__init__构造函数(base.py#L22-L35)的签名如下:
def __init__( self, model_name: str, api_key: Optional[str] = None, api_base: str = "https://api.together.xyz/v1", **kwargs: Any, ) -> None: api_key = api_key or os.environ.get("TOGETHER_API_KEY", None) super().__init__( model_name=model_name, api_key=api_key, api_base=api_base, **kwargs, )从这里可以提炼出三个关键结论:
model_name是唯一必填位置参数,直接决定调用哪个 Together 嵌入模型(例如在 API 文档中体现为形如togethercomputer/...的模型 API 字符串),并会在后续请求体中以"model"字段透传给服务端;api_key是可选的,显式传入优先,否则自动读取TOGETHER_API_KEY环境变量——这意味着推荐做法是先export TOGETHER_API_KEY=...再实例化,避免把密钥硬编码进代码;**kwargs透传给父类,因此继承自BaseEmbedding的通用字段(如embed_batch_size、callback_manager)同样可以在构造TogetherEmbedding时一并指定。
单元测试 tests/test_embeddings_together.py 验证了这一点:TogetherEmbedding(model_name="fake_model_name", api_key="fake key")可以正常实例化,且是BaseEmbedding的实例。
调用方式与实例化示例
结合仓库中的 Notebook 示例(docs/examples/embeddings/together.ipynb),最典型的用法是先设置环境变量,再构造嵌入模型并调用:
import os os.environ["TOGETHER_API_KEY"] = "your_together_api_key" from llama_index.embeddings.together import TogetherEmbedding embed_model = TogetherEmbedding( model_name="togethercomputer/m2-bert-80M-8k-retrieval", )如果不希望依赖环境变量,也可以直接传参,并可按需覆盖默认的 API 地址:
embed_model = TogetherEmbedding( model_name="togethercomputer/m2-bert-80M-8k-retrieval", api_key="your_together_api_key", api_base="https://api.together.xyz/v1", )作为BaseEmbedding子类,其实例可直接作为 LlamaIndex 各组件(索引构建、检索器、查询引擎)的向量化后端,例如通过全局设置接入索引流程,让VectorStoreIndex等组件在文档切分与检索阶段自动调用该模型进行嵌入;也可以直接对文本调用以获得向量:
# 直接调用单文本嵌入 embedding = embed_model.get_text_embedding("LlamaIndex 是一个数据框架") # 查询侧嵌入(例如用于检索阶段对 query 编码) query_embedding = embed_model.get_query_embedding("什么是 LlamaIndex?")同步调用路径与 HTTP 请求细节
TogetherEmbedding的核心同步实现集中在_generate_embedding(base.py#L37-L78)。该方法的签名接受两个参数:text(待编码的句子或文档)与model_api_string(你选择的嵌入模型 API 字符串),返回值为一个浮点数列表(Embedding)。其工作流程如下:
- 构造请求头:
accept: application/json、content-type: application/json、Authorization: Bearer {api_key},即采用标准 Bearer Token 鉴权; - 使用
requests.session()向self.api_base.strip("/") + "/embeddings"发起 HTTP POST 请求,请求体为{"input": text, "model": model_api_string}——注意对api_base做了去尾斜杠处理,避免与/embeddings拼接出双斜杠; - 请求成功后,从响应 JSON 中提取
response.json()["data"][0]["embedding"]作为最终向量返回,这与 OpenAI 兼容的data[0].embedding响应结构一致。
对非 200 状态码的处理体现了工程上的严谨性:
- 若状态码为
429(限流),读取响应头X-RateLimit-Reset中的等待秒数,通过time.sleep(reset_time)阻塞等待后continue重试;若该头不存在或已过期(值为 0),则立即重试; - 其他非 200 状态码一律抛出
ValueError(f"Request failed with status code {response.status_code}: {response.text}"),将服务端返回的原始错误文本附带在异常信息中,便于排查。
由此可以推断:虽然同步路径使用了while True循环,但其作用并非无限重放失败请求,而是为 Together 服务的限流策略(HTTP 429 +X-RateLimit-Reset)提供自适应的等待重试机制。
异步调用路径与批量编码原理
TogetherEmbedding完整实现了异步(async/await)版本,全部异步逻辑对应地落在_agenerate_embedding(base.py#L80-L121)中。与同步版几乎同构:请求头与请求体完全一致,差异在于使用httpx.AsyncClient发送异步 POST,限流等待改用asyncio.sleep(reset_time),从而不阻塞事件循环。
BaseEmbedding要求子类实现四类核心方法,TogetherEmbedding全部补齐(base.py#L123-L147):
| 方法 | 行为 | 底层实现 |
|---|---|---|
_get_text_embedding(text) | 同步编码单条文档文本 | 调用_generate_embedding(text, self.model_name) |
_get_query_embedding(query) | 同步编码单条查询文本 | 调用_generate_embedding(query, self.model_name) |
_get_text_embeddings(texts) | 同步编码文本列表 | 列表推导逐个调用_generate_embedding |
_aget_text_embedding(text) | 异步编码单条文档文本 | 调用_agenerate_embedding(text, self.model_name) |
_aget_query_embedding(query) | 异步编码单条查询文本 | 调用_agenerate_embedding(query, self.model_name) |
_aget_text_embeddings(texts) | 异步编码文本列表 | asyncio.gather(*[自举多个 _agenerate_embedding]) |
注意一个从源码结构可以明确推断的实现细节:批量同步方法_get_text_embeddings采用列表推导串行发起多个请求,批量异步方法_aget_text_embeddings则通过asyncio.gather将每个文本的请求并发调度。也就是说,该集成把"批"拆解为逐条独立的 HTTP 调用,并未使用 Together API 的多输入单请求通道——因此对于大量文本的离线索引,优先使用异步变体(如在asyncio.run或事件循环内调用aget_text_embedding/aget_text_embeddings),可获得显著的并发吞吐优势。
对使用者的实操启示:
import asyncio async def main(): texts = ["第一段文档", "第二段文档", "第三段文档"] vectors = await embed_model.aget_text_embeddings(texts) # 并发请求 return vectors vectors = asyncio.run(main())在 LlamaIndex 索引与 RAG 流程中的接入方式
由于TogetherEmbedding是标准BaseEmbedding子类,它可无缝替代任何内置嵌入模型,参与到索引构建(文档Node向量化)、检索(查询与节点向量相似度计算)的完整链路中。最简洁的方式是把实例挂到全局Settings上:
from llama_index.core import Settings Settings.embed_model = embed_model # 后续所有依赖嵌入的组件(如基于向量的索引、检索器)都会默认使用 TogetherEmbedding这样,VectorStoreIndex.from_documents(...)、RetrieverQueryEngine等高层组件在内部调度get_text_embedding/get_query_embedding时,便会自动走通上文的 HTTP 请求与重试逻辑。需要区分的是文档侧与查询侧编码用途:索引阶段以_get_text_embedding路径编码文档块,检索阶段由引擎内部以查询向量(get_query_embedding)去匹配已入库的文档向量。
可观测性与局限小结
从源码实现看,本集成有以下几点值得开发者注意的能力与边界:
- 鉴权简单:仅需 Bearer Token 形式的
api_key(来自参数或TOGETHER_API_KEY环境变量),无复杂签名流程; - 自带限流兜底:同步与异步两条路径均实现了对 429 响应的
X-RateLimit-Reset等待重试,适合在吞吐较高的批量场景下自愈; - 错误可见性高:非限流错误直接抛出携带服务端响应文本的
ValueError; - 批量语义为逐条请求(见上文源码分析),如需吞吐优化应使用异步 gather 版本或在
BaseEmbedding允许的embed_batch_size范围内自行控制并发节奏; - 模型名以
model_name为准,具体可选模型列表与兼容性需以 Together AI 平台当前开放的嵌入模型为准。
综上,围绕 API 参考文档 docs/api_reference/api_reference/embeddings/together.md 中声明的TogetherEmbedding类,其背后是一个"接口标准、实现精简、限流完善"的完整 HTTP 客户端。开发者可沿 base.py、单元测试 与 together.ipynb 三条线索,快速将其落地到自己的 RAG 应用之中。
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考