关于 catsu
Catsu 是统一的 Embedding API 客户端,供需要跨服务商生成和比较向量的开发者使用。它提供 Python 和 Rust 接口、模型发现、自动重试及用量成本跟踪。
主要功能
- 01通过统一 API 调用多个向量服务商
- 02发现并比较模型
- 03支持异步和批量向量调用
- 04自动重试临时错误
- 05自定义维度和输入类型
- 06跟踪 Token 用量与成本
适用场景
- 01切换向量服务商而无需改动代码
- 02为 RAG 或搜索工作流添加向量
- 03按成本或质量比较模型
- 04降低向量维度以节省存储
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ feyninc/ skills --skill catsu安装后在 Claude Code 中输入/catsu确认已加载。
附带文件references/model_comparison.md
详细介绍
Catsu — 统一嵌入 API 客户端
Catsu 为 11 个提供商和 35 多种模型生成嵌入提供统一、一致的接口。内置的重试逻辑、成本跟踪和模型发现功能,无需使用特定于提供商的 SDK。
适用场景
当用户希望执行以下操作时,请使用此技能:
- 通过统一 API 使用任意提供商生成嵌入
- 比较不同提供商的嵌入模型(成本、质量、维度)
- 在 RAG 工作流、搜索系统或推荐引擎中添加嵌入
- 切换提供商而无需更改应用代码
- 跟踪嵌入调用中的令牌用量和成本
- 使用 Matryoshka 嵌入(缩减维度)优化存储
安装
# Python
pip install catsu
# Requires Python 3.10+
# Rust
# Add to Cargo.toml:
# [dependencies]
# catsu = "0.1"
# tokio = { version = "1", features = ["full"] }
设置 — API 密钥
为要使用的提供商设置环境变量:
export OPENAI_API_KEY=<your-openai-key>
export VOYAGE_API_KEY=<your-voyage-key>
export COHERE_API_KEY=<your-cohere-key>
export JINA_API_KEY=<your-jina-key>
export MISTRAL_API_KEY=<your-mistral-key>
export GOOGLE_API_KEY=<your-google-key> # or GEMINI_API_KEY
export TOGETHER_API_KEY=<your-together-key>
export MIXEDBREAD_API_KEY=<your-mixedbread-key>
export NOMIC_API_KEY=<your-nomic-key>
export DEEPINFRA_API_KEY=<your-deepinfra-key>
export CLOUDFLARE_API_TOKEN=<your-cloudflare-token> # + CLOUDFLARE_ACCOUNT_ID
只需配置实际调用的提供商对应的密钥。
基本用法
Python
from catsu import Client
client = Client()
# Embed text — provider:model format
response = client.embed(
model="openai:text-embedding-3-small",
input=["Hello, world!", "How are you?"]
)
print(response.embeddings) # [[0.012, -0.034, ...], [...]]
print(response.dimensions) # 1536
print(response.usage.tokens) # 10
print(response.usage.cost) # 0.000002
print(response.latency_ms) # 142.5
Rust
use catsu::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new()?;
let response = client.embed(
"openai:text-embedding-3-small",
vec!["Hello, world!".to_string()],
).await?;
println!("Dimensions: {}", response.dimensions);
println!("Cost: ${}", response.usage.cost.unwrap_or(0.0));
Ok(())
}
模型指定方式
指定要使用的模型有三种方式:
client = Client()
# 1. Provider prefix (recommended)
response = client.embed(model="voyageai:voyage-3", input="hello")
# 2. Explicit provider parameter
response = client.embed(provider="voyageai", model="voyage-3", input="hello")
# 3. Auto-detection (if model name is unique across providers)
response = client.embed(model="voyage-3", input="hello")
输入类型 — 查询与文档
许多提供商会针对搜索查询和存储文档采用不同的嵌入优化方式:
# For search queries (short, question-like)
response = client.embed(
model="voyageai:voyage-3",
input=["what is attention?"],
input_type="query",
)
# For documents being indexed (longer content)
response = client.embed(
model="voyageai:voyage-3",
input=["The attention mechanism allows models to..."],
input_type="document",
)
支持输入类型的提供商:VoyageAI、Cohere(v3 及更高版本为必需项)、Jina、Mistral、Gemini、Nomic。
自定义维度(Matryoshka 嵌入)
稍微牺牲质量,缩减嵌入维度以节省存储空间并提高速度:
# OpenAI: 1536 → 256 dimensions
response = client.embed(
model="openai:text-embedding-3-small",
input=["hello"],
dimensions=256,
)
print(response.dimensions) # 256
支持自定义维度的提供商:OpenAI、VoyageAI、Cohere、Jina、Mistral、Gemini、Nomic。
支持的提供商和模型
| 提供商 | 模型 | 维度 | 最大令牌数 | 输入类型 | 自定义维度 |
|---|---|---|---|---|---|
| OpenAI | text-embedding-3-small, 3-large, ada-002 | 1536, 3072, 1536 | 8191 | 否 | 是 |
| VoyageAI | voyage-3, voyage-code-3, voyage-finance-2, voyage-law-2, voyage-multilingual-2, voyage-multimodal-3 | 1024 | 32000 | 是 | 是 |
| Cohere | embed-v4.0, embed-english-v3.0, embed-multilingual-v3.0 | 1024 | 128000 | 必需(v3+) | 是 |
| Jina | jina-embeddings-v4, v3, jina-code-v2 | 1024 | 32768 | 是 | 是 |
| Mistral | mistral-embed, codestral-embed-2505 | 1024 | 32768 | 是 | 是 |
| Gemini | gemini-embedding-001 | 768 | 2048 | 是 | 是(128-3072) |
| Together AI | BAAI/bge models | 1024 | 8192 | 否 | 否 |
| Mixedbread | mxbai-embed models | 1024 | 512 | 否 | 否 |
| Nomic | nomic-embed-text-v1.5 | 768 | 8192 | 是 | 是 |
| DeepInfra | BAAI/bge models | 1024 | 8192 | 否 | 否 |
| Cloudflare | BGE, Qwen models | 768-1024 | 512-8192 | 否 | 否 |
模型发现
from catsu import Client
# List all available models
all_models = Client.list_models()
# Filter by provider
openai_models = Client.list_models("openai")
for m in openai_models:
print(f"{m.name}: {m.dimensions}d, ${m.cost_per_million_tokens}/M tokens")
# Get specific model info
model = Client.get_model("openai", "text-embedding-3-small")
print(f"Max tokens: {model.max_tokens}")
print(f"Supports dimensions: {model.supports_dimensions}")
# Find model by name (auto-detect provider)
model = Client.find_model_by_name("voyage-3")
print(f"Provider: {model.provider}")
模型选择指南
| 使用场景 | 推荐模型 | 原因 |
|---|---|---|
| 通用、低成本 | openai:text-embedding-3-small | 性价比最佳 |
| 高质量检索 | voyageai:voyage-3 | MTEB 评分领先 |
| 代码搜索 | voyageai:voyage-code-3 或 jina:jina-code-v2 | 针对代码优化训练 |
| 法律/金融领域 | voyageai:voyage-law-2 / voyage-finance-2 | 针对特定领域 |
| 多语言内容 | cohere:embed-multilingual-v3.0 或 voyageai:voyage-multilingual-2 | 支持 100 多种语言 |
| 长文档(128K) | cohere:embed-v4.0 | 128K 令牌上下文 |
| 免费/可自托管 | together:BAAI/bge-large-en-v1.5 | 开源模型,成本低 |
| 多模态(文本 + 图像) | voyageai:voyage-multimodal-3 或 jina:jina-embeddings-v4 | 混合内容 |
详细基准测试和成本分析请参阅 references/model_comparison.md。
重试与错误处理
Catsu 会自动处理暂时性故障:
client = Client(
max_retries=5, # Default: 3
timeout=60, # Default: 30 seconds
)
# Retries automatically on: 429, 408, 409, 500, 502, 503, 504
# Uses exponential backoff with jitter
# Respects Retry-After headers
显式错误处理
from catsu.utils.errors import (
RateLimitError,
AuthenticationError,
ModelNotFoundError,
MissingApiKeyError,
)
try:
response = client.embed(model="voyage-3", input="hello")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except AuthenticationError:
print("Invalid API key")
except ModelNotFoundError as e:
print(f"Unknown model: {e}")
except MissingApiKeyError as e:
print(f"Set {e.provider} API key")
高级配置
按请求覆盖 API 密钥
import os
response = client.embed(
model="openai:text-embedding-3-small",
input="hello",
api_key=os.environ["ALTERNATE_OPENAI_KEY"],
)
HTTP 代理和自定义 CA
# Python
client = Client(proxy="http://proxy:8080")
# Rust
let config = HttpConfig {
proxy: Some("http://proxy:8080".to_string()),
ca_cert_pem: Some(cert_pem_string),
..Default::default()
};
let client = Client::with_config(config)?;
使用上下文管理器进行清理
# Sync
with Client() as client:
response = client.embed("voyage-3", "hello")
# Async
async with Client() as client:
response = await client.aembed("voyage-3", "hello")
NumPy 转换
response = client.embed("voyage-3", ["text1", "text2"])
arr = response.to_numpy() # shape: (2, 1024)
异步支持
import asyncio
from catsu import Client
async def embed_batch():
async with Client() as client:
response = await client.aembed(
model="openai:text-embedding-3-small",
input=["text1", "text2", "text3"],
)
return response.embeddings
embeddings = asyncio.run(embed_batch())
与 Chonkie 集成
Catsu 可作为 Chonkie RAG 管道的嵌入提供方:
pip install "chonkie[catsu]"
from chonkie import Pipeline
# Use catsu as the embedding backend
docs = (Pipeline()
.chunk_with("recursive", chunk_size=512)
.refine_with("embeddings", embedding_model="catsu:voyage-3")
.store_in("qdrant", url="http://localhost:6333", collection="docs")
.run(texts=documents)
)
也可以通过 Chonkie 的 AutoEmbeddings 直接使用 Catsu 的嵌入:
from chonkie import AutoEmbeddings
embed = AutoEmbeddings.get_embeddings("catsu:openai:text-embedding-3-small")
vectors = embed.embed_batch(["text1", "text2"])
评论
支持 Markdown