ark-embedding
Ark-Embedding
- 火山方舟大模型服务
- 提供两种SDK接入方式
- OPENAI SDK(兼容)
- 火山方舟 SDK
- 使用类似 openai 风格的 token 认证鉴权
- 可以在请求中携带,通常在 env 的 ARK_API_KEY 中
SDK 安装
火山方舟支持 Python、Go、Java 三种官方 SDK,并原生兼容 OpenAI 协议。
1. 官方 SDK 快速概览
| 语言 | 最低版本要求 | 主要安装/管理命令 | 备注 |
|---|---|---|---|
| Python | Python 3.7+ | pip install 'volcengine-python-sdk[ark]' |
支持 -U 参数升级 |
| Go | Go 1.18+ | go get -u github.com/volcengine/volcengine-go-sdk |
依赖 go mod 管理 |
| Java | JDK 1.8+ | Maven (pom.xml) 或 Gradle (build.gradle) |
仅限服务端,不支持 Android |
openai 兼容
pip install --upgrade "openai>=1.0"
- 快速开始
from openai import OpenAI
import os
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 环境变量中配置您的API Key
api_key=os.environ.get("ARK_API_KEY"),
)
completion = client.chat.completions.create(
# Replace with Model ID .
model="doubao-seed-1-6-251015",
messages = [
{"role": "user", "content": "Hello"},
],
)
print(completion.choices[0].message.content)
- 设置额外字段
- 传入OpenAI SDK中不支持的字段,可以通过 extra_body 字典传入,如开关模型是否深度思考的 thinking 字段。
from openai import OpenAI
import os
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 环境变量中配置您的API Key
api_key=os.environ.get("ARK_API_KEY"),
)
completion = client.chat.completions.create(
# Replace with Model ID .
model="doubao-seed-1-6-251015",
messages = [
{"role": "user", "content": "Hello"},
],
extra_body={
"thinking": {
"type": "disabled", # 不使用深度思考能力
# "type": "enabled", # 使用深度思考能力
}
}
)
print(completion.choices[0].message.content)
- 设置自定义header
- 可以用于传递额外信息,如配置 ID来串联日志,使能数据加密能力。
from openai import OpenAI
import os
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 环境变量中配置您的API Key
api_key=os.environ.get("ARK_API_KEY"),
)
completion = client.chat.completions.create(
# Replace with Model ID .
model="doubao-seed-1-6-251015",
messages = [
{"role": "user", "content": "Hello"},
],
# 自定义request id
extra_headers={"X-Client-Request-Id": "202406251728190000B7EA7A9648AC08D9"}
)
print(completion.choices[0].message.content)
- 文本向量化 Embedding
- 注意:多模态向量化能力模型不支持 OpenAI API ,如需使用请使用 方舟 SDK,详情请参考多模态向量化。
from openai import OpenAI
import os
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 环境变量中配置您的API Key
api_key=os.environ.get("ARK_API_KEY"),
)
resp = client.embeddings.create(
# Replace with Model ID .
model="doubao-embedding-large-text-240915",
input=["Nice day."]
)
print(resp)
- LangChain OpenAI SDK
- 安装 LangChain OpenAI SDK:pip install langchain-openai
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
import os
llm = ChatOpenAI(
# 环境变量中配置您的API Key
openai_api_key=os.environ.get("ARK_API_KEY"),
# The base URL for model invocation
openai_api_base="https://ark.cn-beijing.volces.com/api/v3",
# Replace with Model ID
model="doubao-seed-1-6-251015",
)
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate.from_template(template)
question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
llm_chain = prompt | llm
print(llm_chain.invoke(question))
SDK 常见使用示例
- 当您使用官方 SDK 时,设置自定义header等典型的使用,可以参考本说明。
- 设置超时&重试次数,超时设置(timeout):适用于对响应时间较长的场景(如深度思考模型回复问题时间较长),避免请求时间超时导致服务中断,这里推荐30分钟(1800秒)。
- Python SDK:默认 60秒 连接超时(建立网络连接的最大等待时间),600 秒 socket 超时(连接建立后的数据传输超时)。
- Java SDK:默认 60秒 连接超时,600 秒 socket 超时。
- Go SDK:默认 600s 端到端的总超时(从请求发起至响应接收的总超时)。
- 重试次数(max_retries):适用于网络不稳定场景,自动重试因瞬时故障(如网络波动)失败的请求,默认2次,即请求失败默认会再重试2次,您可以按需配置。
import os
# 通过命令安装方舟SDK pip install 'volcengine-python-sdk[ark]' .
from volcenginesdkarkruntime import Ark
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
# 设置服务响应超时时间,单位秒,推荐1800秒及以上
timeout=1800,
# 设置重试次数
max_retries=2,
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
- 使用Access Key鉴权
- 当需要通过火山引擎云服务的标准鉴权体系(Access Key/Secret Key)认证时使用。
- 使用 Access Key 鉴权的实现原理是通过接口 GetApiKey 获取临时 API Key 进行鉴权,此接口限流较低,务必使用单例模式进行请求,避免因限流导致鉴权失败,可参考单例请求
import os
# 通过命令安装方舟SDK pip install 'volcengine-python-sdk[ark]' .
from volcenginesdkarkruntime import Ark
client = Ark(
ak=os.environ.get("VOLC_ACCESSKEY"),
sk=os.environ.get("VOLC_SECRETKEY"),
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
- 设置自定义 header
- 自定义的 header 字段采用键值对(key-value)结构,以对象形式呈现,具体格式示例如下:
- 可以用于传递额外信息,如配置 ID来串联日志,使能数据加密能力。支持该字段的接口有 对话(Chat) API、批量(Chat)API,下面是典型示例。
{
"key1": "value1",
"key2": "value2",
...,
"keyN": "valueN"
}
问题定位 您可以在请求时,为多个请求设置 key 为 X-Client-Request-Id,value 配置为自定义的 ID,并提供 ID 给方舟售后团队,为您串联客户端和服务端日志,方便问题定位。
import os
# 通过命令安装方舟SDK pip install 'volcengine-python-sdk[ark]' .
from volcenginesdkarkruntime import Ark
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
completion = client.chat.completions.create(
# Replace with Model ID .
model = "doubao-seed-1-6-251015",
messages = [
{"role": "user", "content": "Hello"},
],
# 自定义request id
extra_headers={"X-Client-Request-Id": "My-Request-Id"}
)
print(completion.choices[0].message.content)
文本向量化
- 文本字符串转换向量
- 通过调用doubao-embedding-text-240715模型,将输入的文本字符串转换为向量表示,并输出向量维度和前10维数值。
- 注意为获得更好性能,建议文本数量总token不超过4096,或者文本条数不超过4。
import os
from volcenginesdkarkruntime import Ark
# 初始化客户端
client = Ark(
# 从环境变量中读取您的方舟API Key
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3"
)
response = client.embeddings.create(
model="doubao-embedding-text-240715",
input="Function Calling 是一种将大模型与外部工具和 API 相连的关键功能",
encoding_format="float"
)
# 打印结果
print(f"向量维度: {len(response.data[0].embedding)}")
print(f"前10维向量: {response.data[0].embedding[:10]}")
- 输入文本文件逐行转换
- 向量化模型可以基于您上传的文档生成嵌入向量。此处以embedding_text.txt作为示例文件,您可以通过代码对文本文件逐行转化成向量。
import os
from volcenginesdkarkruntime import Ark
client = Ark(
# 从环境变量中读取您的方舟API Key
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3"
)
# 从文件读取文本并生成向量
with open("embedding_text.txt", "r", encoding="utf-8") as f:
# 按行分割文本(每行作为一个独立输入)
texts = [line.strip() for line in f if line.strip()]
response = client.embeddings.create(
model="doubao-embedding-text-240715",
input=texts,
encoding_format="float"
)
# 打印结果
print(f"处理文本数量: {len(response.data)}")
print(f"首个文本向量维度: {len(response.data[0].embedding)}")
相似度计算
- Doubao-embedding向量间相似度得分可以使用余弦相似度作为计算方式,余弦相似度计算拆分为下面两步:
- 第一步: 请求doubao-embedding接口得到embedding,将embedding向量L2_norm处理;
- 第二步: 对norm处理后的向量进行点积计算得到余弦相似度;
向量降维
- 向量化是通过向量来表征文本、图像等非结构化数据的过程,让计算机能明白语言、图像等的含义。其中标注词义的维度是描述向量化后向量中数字的个数。在文本向量化场景,每个维度对应文本的一个特征。
- 维度更多:以更多独立特征标注词语来捕捉语义细节,提升表征精度。但会导致数据量膨胀,带来更高的存储成本(内存/磁盘占用)和计算开销(相似度计算、模型推理耗时)。
- 维度更低:以更少特征标注词语,可能损失部分细节。但数据量缩减,存储效率与计算速度会提升,资源消耗以及成本更低。
- 下列模型支持多种维度,您可通过向量降维,选择合适的维度来向量化文本,平衡“语义精度”、”计算速度“与“资源成本”三者成本。
豆包向量化模型 (Doubao Embedding) 规格表
| 模型 ID (Model ID) | 支持维度 | 备注 |
|---|---|---|
| doubao-embedding-large-text-250515 | 2048 (支持 2048、1024、512、256 降维使用) | 需要 L2 归一化后使用。L2 归一化是将向量中每个元素除以该向量的 L2 范数(各元素平方和的平方根),使向量长度为 1,从而消除量纲差异并保留相对大小关系。 |
| doubao-embedding-large-text-240915 | 4096 (支持 2048、512、1024 降维使用) | 无 |
| doubao-embedding-text-240715 | 2560 (支持 512、1024、2048 降维使用) | 无 |
| doubao-embedding-text-240515 | 2048 (支持 512、1024 降维使用) | 无 |
推荐用法:常规降维方式以doubao-embedding-text-240715模型为例,最高维度2560可以压缩到512, 1024, 2048维度存储检索,维度越高越接近最高维度效果。 如何降维度&计算相似度? 降维度: 将embedding接口获取的向量直接截取前dim维度; 计算相似度: 对截取后的embedding做余弦相似度计算;
# 降维 + L2_norm
def sliced_norm_l2(vec: List[float], dim=2560) -> List[float]:
# dim 取值 512,1024,2048
norm = float(np.linalg.norm(vec[ :dim]))
return [v / norm for v in vec[ :dim]]
# 余弦相似度计算
query_doc_relevance_score_2560d = np.matmul(
sliced_norm_l2(embeddings[0], 2560), #查询向量
sliced_norm_l2(embeddings[1], 2560) #文档向量
)
- 针对doubao-embedding-large-text-250515模型,需要降维后L2归一化使用。模型支持多种嵌入维度:[2048、1024、512、256] ,即使在较低维度下性能下降也较小。
- 如何降维度&计算相似度?
- 降维度: 将embedding接口获取的向量直接截取前dim维度;
- 归一化:使用 L2 归一化统一向量长度,确保余弦相似度计算准确。 计算相似度: 对截取后的embedding做余弦相似度计算;
def encode(
client, inputs: List[str], is_query: bool = False, mrl_dim: Optional[int] = None
):
# 处理查询文本(添加指令模板优化检索性能)
if is_query:
inputs = [f"Instruct: Given a web search query...\nQuery: {i}" for i in inputs]
# 调用API获取原始向量(未归一化)
resp = client.embeddings.create(
model="doubao-embedding-large-text-250515",
input=inputs,
encoding_format="float",
)
# 转换为张量并降维(截取前mrl_dim维度)
embedding = torch.tensor([d.embedding for d in resp.data], dtype=torch.bfloat16)
if mrl_dim is not None:
assert mrl_dim in [256, 512, 1024, 2048], "仅支持256/512/1024/2048维"
embedding = embedding[:, :mrl_dim]
# 必须执行归一化:L2归一化后才能计算余弦相似度
embedding = torch.nn.functional.normalize(embedding, dim=1, p=2).float().numpy()
return embedding
最佳实践
- 下列程序实现了将查询文本和资料库文本向量匹配的功能。我们以embedding_text.txt的多行文本作为资料库,通过调用Doubao-embedding模型生成文本向量。当程序接收到用户的查询文本时,将其向量化并通过余弦相似度匹配资料库的向量,最终返回最相关的前3条文本及对应相似度分数。
第一步:客户端初始化
导入所需的库包,并设置 API Key,为后续的数据处理和分析做准备。
import os
# 导入火山引擎大模型SDK
from volcenginesdkarkruntime import Ark
# 初始化客户端
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3"
)
第二步:从文件读取文本并生成向量
读取包含文本的embedding_text.txt文件,调用文本向量模型 API 逐行生成文本对应的向量,并将文本和向量保存为 JSON 文件。
def generate_and_save_embeddings(file_path="embedding_text.txt", output_path="embeddings.json"):
with open(file_path, "r", encoding="utf-8") as f:
texts = [line.strip() for line in f if line.strip()]
# 调用向量化API
response = client.embeddings.create(
model="doubao-embedding-text-240715",
input=texts,
encoding_format="float"
)
# 构建结果并保存
results = [{"text": text, "embedding": data.embedding}
for text, data in zip(texts, response.data)]
with open(output_path, "w", encoding="utf-8") as f:
json.dump(results, f)
print(f"已生成并保存 {len(results)} 条向量至 {output_path}")
return results
第三步:加载预计算的向量数据
从 JSON 文件加载预计算的文本向量数据,为后续的相似度计算做准备。
def load_embeddings(file_path="embeddings.json"):
with open(file_path, "r", encoding="utf-8") as f:
return json.load(f)
第四步:定义计算余弦相似度函数和搜索相似文本函数
利用余弦相似度来度量文本之间的相似性,实现了一个基于内容的文本搜索功能。 用户可以通过输入查询文本,检索与该查询文本最相关的文本。
# 定义计算余弦相似度函数
def cosine_similarity(a, b):
a = np.array(a)
b = np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 定义search_similar_text 函数:搜索与查询文本最相似的前N条文本
def search_similar_text(query_text, embeddings, top_n=3):
# 生成查询文本的向量
query_response = client.embeddings.create(
model="doubao-embedding-text-240715",
input=[query_text],
encoding_format="float"
)
query_embedding = query_response.data[0].embedding
# 计算相似度
for item in embeddings:
item["similarity"] = cosine_similarity(item["embedding"], query_embedding)
# 排序并返回结果
sorted_results = sorted(embeddings, key=lambda x: x["similarity"], reverse=True)
return sorted_results[:top_n]
第五步:测试搜索功能
测试搜索功能,调用 search_similar_text 函数查询与query变量相关的文本,并返回与该查询文本最相关的前 3 条文本及其相似度分数。
# 示例:生成向量并搜索
if __name__ == "__main__":
# 生成或加载向量
try:
embeddings = load_embeddings()
print(f"已加载 {len(embeddings)} 条预计算向量")
except FileNotFoundError:
print("未找到预计算向量,将从文件生成...")
embeddings = generate_and_save_embeddings()
# 执行搜索(示例查询:上下文缓存机制)
query = "上下文缓存(Context API)是方舟提供的一个高效的缓存机制,旨在为您优化生成式AI在不同交互场景下的性能和成本。"
results = search_similar_text(query, embeddings, top_n=3)
# 打印结果
print(f"\n搜索查询: '{query}'")
for i, result in enumerate(results, 1):
print(f"\nTop {i} (相似度: {result['similarity']:.4f}):")
print(f"{result['text'][:200]}...") # 显示前200个字符
请求参数
-
model string 必选 您需要调用的模型的 ID (Model ID),开通模型服务,并查询 Model ID 。 您也可通过 Endpoint ID 来调用模型,获得限流、计费类型(前付费/后付费)、运行状态查询、监控、安全等高级能力,可参考获取 Endpoint ID。
-
input string / string[] 必选 需要向量化的内容列表,支持中文、英文。输入内容需满足下面条件: 不得超过模型的最大输入 token 数。doubao-embdding 模型,每个列表元素(并非单次请求总数)最大输入token 数为 4096。 不能为空列表,列表的每个成员不能为空字符串。 单条文本以 utf-8 编码,长度不超过 100,000 字节。 为获得更好性能,建议文本数量总token不超过4096,或者文本条数不超过4。
-
encoding_format string / null 默认值 float 取值范围: float、base64、null。 表示 embedding 返回的格式。
响应参数
id string 本次请求的唯一标识 。
model string 本次请求实际使用的模型名称和版本。
created integer 本次请求创建时间的 Unix 时间戳(秒)。
object string 固定为 list。
data object 本次请求的算法输出内容。
data.index integer 向量的序号,与请求参数 input 列表中的内容顺序对应。
data.embedding float[] 对应内容的向量化结果。
data.object string 固定为 embedding。
usage object 本次请求的 token 用量。
usage.prompt_tokens integer 输入内容 token 数量。
usage.total_tokens integer 本次请求消耗的总 token 数量(输入 + 输出)。
多模态向量化
Doubao-embedding-vision 是由字节跳动研发的多模态向量化模型。它能将文本、图片以及视频等混合输入内容转换为统一的向量表示,从而帮助您更高效地处理跨模态数据,实现精准的文搜图、图搜图和图文混合搜索。 当前模型支持以下几种向量输出类型: 稠密向量 (Dense Embedding):所有版本均默认支持。 稀疏向量 (Sparse Embedding):从 doubao-embedding-vision-250615 版本起支持,且仅支持文本输入。
多模态向量模型 (Vision Embedding)
| 模型版本 | 输入能力 | 稀疏向量 (Sparse) | instructions 字段 |
|---|---|---|---|
vision-250328 |
最多 1 文本 + 1 图片 | 不支持 | 不支持 |
vision-250615 |
不限数量文本/图片/视频 | 支持(仅限文本输入) | 不支持 |
vision-251215 及后续 |
不限数量文本/图片/视频 | 支持(仅限文本输入) | 支持 |
-
注意:【重要】instructions 字段的配置直接决定模型推理效果。为了显著提升向量表示的精度,您需要根据具体的业务场景来定制该指令。请勿直接使用系统默认值。详情请参考设置 instructions 字段(推荐)。
-
本文档不包含 instructions 用法
-
开启稀疏向量(Sparse Embedding)
-
仅 doubao-embedding-vision-250615 及后续版本支持。稀疏向量仅支持纯文本输入。
- TOS vectors 不支持稀疏向量,在与 tos vectors 联合使用的场景,请不要使用稀疏向量
-
通过独立的 sparse_embedding 字段控制,示例:
{
"model": "doubao-embedding-vision-251215",
"input": [
{
"type":"text",
"text":"天很蓝"
}
],
"sparse_embedding": {
"type":"enabled" # 开启稀疏向量,默认值为 "disabled"
},
"encoding_format":"float"
}
设置向量维度 dimensions
向量化是通过向量来表征文本、图像等非结构化数据的过程,让计算机能理解语言、图像等的含义。其中,向量维度是描述向量化后向量中元素的个数(标注词义/图像特征的维度)。在多模态向量化场景,每个维度对应文本的一个特征或者是对应图像的像素、色彩等视觉特征。 doubao-embedding-vision-250615及后续版本支持通过dimensions 参数指定稠密向量的输出维度,对输出的data.embedding 字段生效。 注意 目前仅支持对稠密向量设置维度,稀疏向量(固定维度)不支持。 doubao-embedding-vision-250328 模型不支持此字段,请参考通过编码实现向量降维。
{
"model": "doubao-embedding-vision-250615",
"input": [
{
"type":"text",
"text":"天很蓝"
}
],
"dimensions": 1024, #设置向量维度
"encoding_format":"float"
}
图片格式说明
图片传入方式:图片 URL 或图片 Base64 编码。用图片 URL 方式时,需确保图片 URL 可被访问。 图片文件容量:单张图片小于 10 MB。使用 base64 编码,请求中请求体大小不可超过 64 MB。 图片像素说明:模型能够支持尺寸更加灵活的图片,传入图片满足下面条件:图片宽高长度(单位 px):大于 14。图片像素(宽*高,单位 px):小于 3600万。 图片数量说明:doubao-embedding-vision-250615 及后续版本 支持不限数量的视频、文本和图片混合输入。doubao-embedding-vision-250328 模型仅支持最多 1 文本 和 1 图片 输入。
最佳实践:多模态相似度匹配示例
第一步:导入库包 导入所需的库包,并设置 API Key,为后续的数据处理和分析做准备。
import os
import numpy as np
from volcenginesdkarkruntime import Ark
from sklearn.metrics.pairwise import cosine_similarity
第二步:获取向量 定义一个函数将单个文本或图片转换为向量表示。支持两种输入类型:文本和图片 URL。调用doubao-embedding-vision-241215模型获取float格式向量,再转换为numpy数组并展平为一维向量。
def get_embedding(input_data, input_type="text"):
"""调用火山引擎API获取单个文本或图片的向量表示"""
client = Ark(api_key=os.environ.get("ARK_API_KEY"))
if input_type == "text":
input_item = {"type": "text", "text": input_data}
elif input_type == "image_url":
input_item = {"type": "image_url", "image_url": {"url": input_data}}
else:
raise ValueError("输入类型仅支持'text'或'image_url'")
try:
resp = client.multimodal_embeddings.create(
model="doubao-embedding-vision-241215",
encoding_format="float",
input=[input_item]
)
if hasattr(resp, 'data') and hasattr(resp.data, 'embedding'):
embedding = resp.data['embedding']
# 确保向量是numpy数组并展平为一维
embedding = np.array(embedding).flatten()
return embedding
else:
raise ValueError("API响应格式不符合预期,无法获取嵌入向量")
except Exception as e:
print(f" 获取向量失败,输入类型: {input_type}, 错误: {str(e)}")
raise
第三步:生成向量库 批量处理图片 URL 列表,生成对应的向量表示,并构建向量库。
def generate_image_embeddings(image_urls):
"""批量生成图片向量并构建向量库"""
print(f"[1/3] 开始生成 {len(image_urls)} 张图片的向量...")
embeddings = []
for i, url in enumerate(image_urls):
try:
embedding = get_embedding(url, "image_url")
embeddings.append({
"image_url": url,
"embedding": embedding
})
print(f" [{i+1}/{len(image_urls)}] 成功: {url}")
except Exception as e:
print(f" [{i+1}/{len(image_urls)}] 失败: {url} - {str(e)}")
continue
if not embeddings:
raise ValueError("所有图片向量生成失败")
print(f"[2/3] 完成: {len(embeddings)} 个有效向量")
return embeddings
第四步:图片相似度计算 利用余弦相似度来度量文本与图片之间的相似性,实现了一个基于内容的图片搜索功能。用户可以通过输入文本描述,检索与该描述最相关的图片。
def search_similar_images(query_embedding, embeddings, top_n=1, query_type="文本"):
"""搜索与查询向量最相似的图片"""
print(f"\n[3/3] 开始搜索与{query_type}最相似的图片...")
results = []
# 确保查询向量是numpy数组且维度正确
query_vec = np.array(query_embedding).reshape(1, -1)
for item in embeddings:
# 确保向量是numpy数组并调整为二维数组用于相似度计算
item_vec = np.array(item["embedding"]).reshape(1, -1)
similarity = cosine_similarity(query_vec, item_vec)[0][0]
results.append({
"image_url": item["image_url"],
"similarity": similarity
})
results.sort(key=lambda x: x["similarity"], reverse=True)
print(f" - 相似度计算完成,共 {len(results)} 个结果")
return results[:top_n]
第五步:示例用法 测试搜索功能,调用generate_image_embeddings函数生成图片向量库,使用文本查询搜索相似图片,并返回最相似的结果。示例代码如下:
if __name__ == "__main__":
image_urls = [
"https://ark-project.tos-cn-beijing.volces.com/doc_image/Fruit1.jpg",
"https://ark-project.tos-cn-beijing.volces.com/doc_image/Fruit2.jpg",
"https://ark-project.tos-cn-beijing.volces.com/doc_image/Fruit3.jpg",
"https://ark-project.tos-cn-beijing.volces.com/doc_image/Fruit4.jpg",
"https://ark-project.tos-cn-beijing.volces.com/doc_image/Fruit5.jpg"
]
query_text = "香蕉"
try:
# 生成图片向量
image_embs = generate_image_embeddings(image_urls)
# 生成文本向量
text_emb = get_embedding(query_text, "text")
print(f"文本向量维度: {len(text_emb)}")
# 搜索相似图片
similar_images = search_similar_images(text_emb, image_embs)
print(f"最相似图片: {similar_images[0]['image_url']}")
print(f"相似度分数: {similar_images[0]['similarity']:.4f}")
except Exception as e:
print(f"程序失败: {e}")
相关技术
通过编码实现向量降维
注意 doubao-embedding-vision-250615及后续版本支持设置向量维度 dimensions。 稀疏向量不支持降维。 doubao-embedding-vision-241215向量维度3072维,不支持降维使用 doubao-embedding-vision-250328模型支持最高维度2048可以压缩到1024维度存储检索,维度越高越接近最高维度效果。
如何降维度&计算相似度?
降维度: 将embedding接口获取的向量直接截取前dim维度; 计算相似度: 对截取后的embedding做余弦相似度计算;
# 降维+ L2_norm
def sliced_norm_l2(vec: List[float], dim=2048) -> List[float]:
# dim 为1024
norm = float(np.linalg.norm(vec[ :dim]))
return [v / norm for v in vec[ :dim]]
# 余弦相似度计算
query_doc_relevance_score_2048d = np.matmul(
sliced_norm_l2(embeddings[0], 2048), #查询向量
sliced_norm_l2(embeddings[1], 2048) #文档向量
)
Base64 编码输入
如果你要传入的视频/图片在本地,你可以将这个视频/图片转化为 Base64 编码,然后提交给大模型。下面是一个简单的转换示例代码。 注意 传入 Base64 编码格式时,请遵循以下规则: 传入的是图片: 格式遵循data:image/<图片格式>;base64,<Base64编码>,其中, 图片格式:jpeg、png、gif等,支持的图片格式详细见图片格式说明。 Base64 编码:图片的 Base64 编码。 传入的是视频: 格式遵循data:video/<视频格式>;base64,<Base64编码>,其中, 视频格式:MP4、AVI等,支持的视频格式详细见视频格式说明。 Base64 编码:视频的 Base64 编码。
# 定义方法将指定路径图片转为Base64编码
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
# 需要传给大模型的图片
image_path = "path_to_your_image.jpg"
# 将图片转为Base64编码
base64_image = encode_image(image_path)
转换后,图片的url格式参考如下:
{
"type": "image_url",
"image_url": {
"url": f"data:image/<IMAGE_FORMAT>;base64,{base64_image}"
}
},
向量批量处理的解决方案
针对 API 仅支持单次传入单张图片的限制,本代码通过异步并发 + 批量分组策略提升图片向量化的批量处理效率:利用 asyncio 创建异步任务,将图片按设定批次分组后并发调用 API;采用 “全组失败回滚” 模式确保每组任务结果一致,支持失败重试,且单独保存成功 / 失败结果(包含向量详情、错误信息和图片输入 URL)。
import asyncio
import os
from pathlib import Path
from volcenginesdkarkruntime import AsyncArk
class MultimodalEmbedder:
"""多模态向量化批量处理工具(全组失败模式)"""
def __init__(self, api_key: str, model: str = "doubao-embedding-vision-241215",
batch_size: int = 10, retries: int = 2):
self.api_key = api_key
self.model = model
self.batch_size = batch_size # 批量大小配置(可扩展分片逻辑)
self.retries = retries # 批量请求重试次数
async def batch_process(self, items_list):
"""核心:异步批量处理向量任务(全组失败)"""
# 1. 初始化批量客户端
async with AsyncArk(max_retries=self.retries) as client:
# 2. 批量创建异步任务(按输入列表分片)
batch_tasks = [
asyncio.create_task(client.multimodal_embeddings.create(model=self.model, input=items))
for items in items_list
]
try:
# 3. 批量等待任务完成(任一失败则全组终止)
batch_results = await asyncio.gather(*batch_tasks)
return batch_results
except Exception:
# 4. 批量清理未完成任务
for task in batch_tasks:
if not task.done():
task.cancel()
raise # 抛出异常,保持全组失败语义
def batch_save(self, batch_results, output_dir: str = "embedding_results"):
"""核心:批量保存向量结果"""
# 1. 初始化输出目录
Path(output_dir).mkdir(exist_ok=True)
# 2. 批量写入结果文件
with open(f"{output_dir}/batch_embeddings.txt", "w", encoding="utf-8") as f:
for idx, result in enumerate(batch_results, 1):
embedding = result.data.get("embedding", [])
f.write(f"批量项 #{idx} | 向量长度: {len(embedding)} | 前20维: {embedding[:20]}...\n")
print(f"批量结果已保存:{output_dir}/batch_embeddings.txt")
if __name__ == "__main__":
# 1. 配置初始化
api_key = os.environ.get("ARK_API_KEY") or input("输入API密钥: ").strip()
if not api_key:
raise ValueError("API密钥不能为空")
# 2. 初始化批量处理器
embedder = MultimodalEmbedder(api_key=api_key, batch_size=10, retries=2)
# 3. 构造批量输入数据
batch_inputs = [
[{"type": "text", "text": "天很蓝,海很深"}, {"type": "image_url", "image_url": {"url": "https://example.com/image1.jpg"}}],
[{"type": "text", "text": "阳光明媚的沙滩"}, {"type": "image_url", "image_url": {"url": "https://example.com/image2.jpg"}}]
]
# 4. 执行批量处理+结果保存
try:
batch_results = asyncio.run(embedder.batch_process(batch_inputs))
embedder.batch_save(batch_results)
print(f"批量处理完成,共生成 {len(batch_results)} 个向量")
except Exception as e:
print(f"批量处理失败: {str(e)}")