mcpField
C
catsu

catsu

github.com/feyninc开发749 次安装19 周前更新
代码仓库

关于 catsu

Catsu 是统一的 Embedding API 客户端,供需要跨服务商生成和比较向量的开发者使用。它提供 Python 和 Rust 接口、模型发现、自动重试及用量成本跟踪。

主要功能

  1. 01通过统一 API 调用多个向量服务商
  2. 02发现并比较模型
  3. 03支持异步和批量向量调用
  4. 04自动重试临时错误
  5. 05自定义维度和输入类型
  6. 06跟踪 Token 用量与成本

适用场景

  1. 01切换向量服务商而无需改动代码
  2. 02为 RAG 或搜索工作流添加向量
  3. 03按成本或质量比较模型
  4. 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。

支持的提供商和模型

提供商模型维度最大令牌数输入类型自定义维度
OpenAItext-embedding-3-small, 3-large, ada-0021536, 3072, 15368191否是
VoyageAIvoyage-3, voyage-code-3, voyage-finance-2, voyage-law-2, voyage-multilingual-2, voyage-multimodal-3102432000是是
Cohereembed-v4.0, embed-english-v3.0, embed-multilingual-v3.01024128000必需(v3+)是
Jinajina-embeddings-v4, v3, jina-code-v2102432768是是
Mistralmistral-embed, codestral-embed-2505102432768是是
Geminigemini-embedding-0017682048是是(128-3072)
Together AIBAAI/bge models10248192否否
Mixedbreadmxbai-embed models1024512否否
Nomicnomic-embed-text-v1.57688192是是
DeepInfraBAAI/bge models10248192否否
CloudflareBGE, Qwen models768-1024512-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-3MTEB 评分领先
代码搜索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.0128K 令牌上下文
免费/可自托管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