Haystack × Eden AI 集成实战:借助 OpenAI 兼容 API 统一多厂商 Embedding 与 Chat 生成
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
Eden AI 是一个聚合型 AI API 网关:通过单个 API Key即可访问 OpenAI、Mistral、Cohere、Google、Jina、Anthropic 等多家厂商的 500+ 模型,并提供欧盟数据驻留(EU data residency)与内置的厂商 fallback。在 Haystack 生态中,edenai-haystack集成包基于官方 OpenAI 组件二次封装,把 Eden AI 的 OpenAI 兼容端点接入 Haystack 的管道体系。本文以version-2.20的 Eden AI API 参考文档 为骨架,完整讲解EdenAIDocumentEmbedder、EdenAITextEmbedder、EdenAIChatGenerator三个组件的参数、用法与底层机制,读完即可在索引管道和 RAG 管道中落地使用。
一、集成概览:三个组件,覆盖 Embedding 与生成全链路
Eden AI 集成遵循 Haystack 组件化设计,全部位于haystack_integrations.components命名空间下,共三个组件:
| 组件 | 继承基类 | 输入 | 输出 | 典型管道位置 |
|---|---|---|---|---|
EdenAIDocumentEmbedder | OpenAIDocumentEmbedder | documents(文档列表) | documents(已附嵌入向量)、meta | 索引管道中DocumentWriter之前 |
EdenAITextEmbedder | OpenAITextEmbedder | text(单个字符串) | embedding(浮点向量)、meta | 查询/RAG 管道中 embedding Retriever 之前 |
EdenAIChatGenerator | OpenAIChatGenerator | messages(ChatMessage列表) | replies(ChatMessage 列表) | ChatPromptBuilder之后 |
三个组件的共同点:只改api_base_url,其余全部复用 Haystack 官方 OpenAI 组件的能力(流式、工具调用、generation_kwargs、序列化等),因此迁移成本极低。模型统一采用 Eden AI 的provider/model命名约定,例如"openai/text-embedding-3-small"、"mistral/mistral-embed"、"anthropic/claude-sonnet-4-5"。
说明:Eden AI 集成代码托管在独立的 haystack-core-integrations 仓库中(包名
edenai-haystack),通过pip安装使用;本文所在仓库 haystack 提供的是 Haystack 核心框架及其文档,其中 OpenAIDocumentEmbedder 与 OpenAIChatGenerator 正是 Eden AI 组件的继承基类,可用于理解其底层行为。
二、环境准备:安装与 API Key 配置
首先安装集成包:
pip install edenai-haystack所有组件都依赖 Eden AI API Key,两种配置方式任选其一:
- 环境变量(推荐):设置
EDENAI_API_KEY,组件初始化时默认通过Secret.from_env_var("EDENAI_API_KEY")自动读取; - 初始化参数:显式传入
api_key,结合 Haystack 的 Secret API 使用:
from haystack.utils import Secret from haystack_integrations.components.embedders.edenai import EdenAIDocumentEmbedder embedder = EdenAIDocumentEmbedder( api_key=Secret.from_token("<your-api-key>"), model="openai/text-embedding-3-small", )三、EdenAIDocumentEmbedder:批量计算文档嵌入
EdenAIDocumentEmbedder负责计算一组 Document的嵌入向量,并把结果写回每个 Document 的embedding字段。它继承自 Haystack 的OpenAIDocumentEmbedder,将请求路由到 Eden AI 的 OpenAI 兼容端点。
3.1 支持的模型
组件内置SUPPORTED_MODELS常量,列出常见可用模型(非穷尽列表):
SUPPORTED_MODELS: list[str] = [ "openai/text-embedding-3-small", "openai/text-embedding-3-large", "mistral/mistral-embed", "cohere/embed-english-v3.0", "google/text-embedding-004", ]即默认同时覆盖 OpenAI、Mistral、Cohere、Google 四家厂商的 embedding 模型,完整模型目录以 Eden AI 官方 models catalog 为准。这意味着你可以用同一套代码在不同厂商模型之间切换,只需修改model字符串。
3.2 完整参数签名与说明
__init__( *, model: str = "openai/text-embedding-3-small", api_key: Secret = Secret.from_env_var("EDENAI_API_KEY"), api_base_url: str | None = "https://api.edenai.run/v3", prefix: str = "", suffix: str = "", batch_size: int = 32, progress_bar: bool = True, meta_fields_to_embed: list[str] | None = None, embedding_separator: str = "\n", timeout: float | None = None, max_retries: int | None = None, http_client_kwargs: dict[str, Any] | None = None ) -> None| 参数 | 默认值 | 说明 |
|---|---|---|
model | "openai/text-embedding-3-small" | Eden AI 嵌入模型名,采用provider/model格式 |
api_key | Secret.from_env_var("EDENAI_API_KEY") | Eden AI API Key,默认读取同名环境变量 |
api_base_url | "https://api.edenai.run/v3" | Eden AI API 基础 URL(即 OpenAI 兼容端点) |
prefix | "" | 添加到每段文本开头的字符串 |
suffix | "" | 添加到每段文本末尾的字符串 |
batch_size | 32 | 每次调用编码的 Document 数量 |
progress_bar | True | 是否显示进度条;生产环境建议关闭以保持日志干净 |
meta_fields_to_embed | None | 需要连同文档文本一起嵌入的 meta 字段列表 |
embedding_separator | "\n" | 拼接 meta 字段与文档文本时使用的分隔符 |
timeout | None | API 调用超时(秒);未设置时回退到OPENAI_TIMEOUT环境变量,再默认 30 秒 |
max_retries | None | 遇到内部错误后重试 Eden AI 的最大次数;未设置时回退到OPENAI_MAX_RETRIES环境变量,再默认 5 次 |
http_client_kwargs | None | 用于配置自定义httpx.Client/httpx.AsyncClient的关键字参数字典 |
超时与重试的默认值来源可以追溯到基类实现:在 openai_document_embedder.py 的_client_kwargs()方法中,timeout未显式设置时读取OPENAI_TIMEOUT(默认"30.0"秒),max_retries读取OPENAI_MAX_RETRIES(默认"5")。Eden AI 组件继承该行为,因此这些环境变量同样生效。
3.3 单独使用
from haystack.dataclasses import Document from haystack_integrations.components.embedders.edenai import EdenAIDocumentEmbedder doc = Document(content="I love pizza!") document_embedder = EdenAIDocumentEmbedder(model="mistral/mistral-embed") result = document_embedder.run([doc]) print(result["documents"][0].embedding) # [0.017020374536514282, -0.023255806416273117, ...]run()接收 Document 列表,返回的documents中每个 Document 的embedding字段即为计算出的向量。
3.4 在索引管道中使用
实际生产中,EdenAIDocumentEmbedder通常位于索引管道的中游:文本转换 → 嵌入 → 写入文档存储:
from haystack import Pipeline from haystack.components.converters import TextFileToDocument from haystack.components.writers import DocumentWriter from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.components.embedders.edenai import EdenAIDocumentEmbedder document_store = InMemoryDocumentStore() indexing_pipeline = Pipeline() indexing_pipeline.add_component("converter", TextFileToDocument()) indexing_pipeline.add_component( "embedder", EdenAIDocumentEmbedder(model="openai/text-embedding-3-small") ) indexing_pipeline.add_component("writer", DocumentWriter(document_store=document_store)) indexing_pipeline.connect("converter", "embedder") indexing_pipeline.connect("embedder", "writer") indexing_pipeline.run({"converter": {"sources": ["./my_document.txt"]}})底层机制:与基类一致,组件采用懒加载客户端设计——warm_up()时才初始化 OpenAI 兼容客户端(见 openai_document_embedder.py),http_client_kwargs通过init_http_client注入自定义httpx配置;批量嵌入由batch_size控制,内部借助more_itertools.batched分块调用 API。若配置了meta_fields_to_embed,文档的 meta 字段会与正文按embedding_separator拼接后一起送入模型,使语义向量融合更多业务维度信息。
四、EdenAITextEmbedder:查询字符串向量化
EdenAITextEmbedder负责把单个字符串(典型场景是用户查询)转成语义向量,用于 embedding 检索。它继承自OpenAITextEmbedder,接口更精简。
4.1 完整参数签名与说明
__init__( *, model: str = "openai/text-embedding-3-small", api_key: Secret = Secret.from_env_var("EDENAI_API_KEY"), api_base_url: str | None = "https://api.edenai.run/v3", prefix: str = "", suffix: str = "", timeout: float | None = None, max_retries: int | None = None, http_client_kwargs: dict[str, Any] | None = None ) -> None各参数含义与EdenAIDocumentEmbedder同名参数一致(model/api_key/api_base_url/prefix/suffix/timeout/max_retries/http_client_kwargs),此处不再重复;差异在于它没有batch_size、progress_bar、meta_fields_to_embed、embedding_separator——因为它每次只处理一段文本。SUPPORTED_MODELS常量与 Document 版相同。
4.2 单独使用
from haystack.utils import Secret from haystack_integrations.components.embedders.edenai import EdenAITextEmbedder embedder = EdenAITextEmbedder( api_key=Secret.from_token("<your-api-key>"), model="openai/text-embedding-3-small", ) result = embedder.run(text="How can I use the Eden AI embedding models with Haystack?") print(result["embedding"]) # [-0.0015687942504882812, 0.052154541015625, 0.037109375...]4.3 在语义检索管道中使用
EdenAITextEmbedder的经典用法是与EdenAIDocumentEmbedder组成"文档向量化 + 查询向量化"的完整语义检索闭环:
from haystack import Pipeline from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack.dataclasses import Document from haystack_integrations.components.embedders.edenai import ( EdenAIDocumentEmbedder, EdenAITextEmbedder, ) document_store = InMemoryDocumentStore(embedding_similarity_function="cosine") documents = [ Document(content="My name is Wolfgang and I live in Berlin"), Document(content="I saw a black horse running"), Document(content="Germany has many big cities"), ] document_embedder = EdenAIDocumentEmbedder(model="openai/text-embedding-3-small") documents_with_embeddings = document_embedder.run(documents)["documents"] document_store.write_documents(documents_with_embeddings) query_pipeline = Pipeline() query_pipeline.add_component( "text_embedder", EdenAITextEmbedder(model="openai/text-embedding-3-small") ) query_pipeline.add_component( "retriever", InMemoryEmbeddingRetriever(document_store=document_store) ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") result = query_pipeline.run({"text_embedder": {"text": "Who lives in Berlin?"}}) print(result["retriever"]["documents"][0])注意两处连接细节:查询管道中通过connect("text_embedder.embedding", "retriever.query_embedding")显式将向量接到检索器的查询嵌入输入;文档存储选用embedding_similarity_function="cosine"以余弦相似度度量向量距离。索引侧用EdenAIDocumentEmbedder离线写入带向量的文档,查询侧用EdenAITextEmbedder在线编码查询,两侧模型保持一致即可获得稳定的检索质量。
五、EdenAIChatGenerator:多模型聊天生成
EdenAIChatGenerator是三者中能力最丰富的组件,通过 Eden AI 的 OpenAI 兼容端点实现聊天补全。它完整继承OpenAIChatGenerator的配置面(流式、工具、generation_kwargs),仅把api_base_url指向 Eden AI,因此可以无缝复用 Haystack 对 ChatMessage 的处理逻辑。
5.1 完整参数签名与说明
__init__( *, api_key: Secret = Secret.from_env_var("EDENAI_API_KEY"), model: str = "openai/gpt-4o-mini", streaming_callback: StreamingCallbackT | None = None, generation_kwargs: dict[str, Any] | None = None, timeout: int | None = None, max_retries: int | None = None, tools: ToolsType | None = None, tools_strict: bool = False, http_client_kwargs: dict[str, Any] | None = None ) -> None| 参数 | 默认值 | 说明 |
|---|---|---|
api_key | Secret.from_env_var("EDENAI_API_KEY") | Eden AI API Key |
model | "openai/gpt-4o-mini" | 聊天模型,provider/model格式,如"anthropic/claude-sonnet-4-5"、"mistral/mistral-large-latest"、"google/gemini-2.5-flash" |
streaming_callback | None | 流式响应时每个 chunk 都会调用的回调函数 |
generation_kwargs | None | 透传给底层生成 API 的关键字参数,如max_tokens、temperature、top_p;Eden AI 特有参数(如 fallback 模型)会原样转发到端点 |
timeout | None | 等待 API 响应的最大秒数 |
max_retries | None | 请求失败时的最大重试次数 |
tools | None | 供模型做函数调用的工具列表、单个 Toolset,或两者混合 |
tools_strict | False | 为True时启用工具调用的严格 schema 约束 |
http_client_kwargs | None | 传给底层 HTTP 客户端的可选关键字参数 |
5.2 工具(Function Calling)支持
EdenAIChatGenerator支持函数调用:tools参数可接收Tool对象列表、单个Toolset或两者混合,方便把相关工具组织成逻辑分组,同时保留独立工具。Haystack 侧的工具机制可参考 Tool 与 Toolset 文档。在基类 openai.py 中可以确认其底层会校验工具名重复、对工具做扁平化/反序列化处理并warm_up_tools,tools_strict=True时还涉及严格 JSON schema 的转换。
5.3 流式输出
组件支持将 LLM 的 token 流式直接输出,只需传入streaming_callback。Haystack 提供开箱即用的print_streaming_chunk,逐 chunk 打印:
from haystack_integrations.components.generators.edenai import EdenAIChatGenerator from haystack.components.generators.utils import print_streaming_chunk from haystack.dataclasses import ChatMessage from haystack.utils import Secret generator = EdenAIChatGenerator( api_key=Secret.from_env_var("EDENAI_API_KEY"), model="mistral/mistral-large-latest", streaming_callback=print_streaming_chunk, ) message = ChatMessage.from_user("What's Natural Language Processing? Be brief.") print(generator.run([message]))5.4 在 RAG 管道中使用
结合LinkContentFetcher、HTMLToDocument与ChatPromptBuilder,可以构建"抓取网页 → 提取内容 → 构造提示 → 生成回答"的完整 RAG 管道:
from haystack import Pipeline from haystack.components.builders import ChatPromptBuilder from haystack.components.fetchers import LinkContentFetcher from haystack.components.converters import HTMLToDocument from haystack.dataclasses import ChatMessage from haystack_integrations.components.generators.edenai import EdenAIChatGenerator fetcher = LinkContentFetcher() converter = HTMLToDocument() prompt_builder = ChatPromptBuilder(variables=["documents"]) llm = EdenAIChatGenerator(model="mistral/mistral-large-latest") message_template = """Answer the following question based on the contents of the article: {{query}}\n Article: {{documents[0].content}} \n """ messages = [ChatMessage.from_user(message_template)] rag_pipeline = Pipeline() rag_pipeline.add_component(name="fetcher", instance=fetcher) rag_pipeline.add_component(name="converter", instance=converter) rag_pipeline.add_component("prompt_builder", prompt_builder) rag_pipeline.add_component("llm", llm) rag_pipeline.connect("fetcher.streams", "converter.sources") rag_pipeline.connect("converter.documents", "prompt_builder.documents") rag_pipeline.connect("prompt_builder.prompt", "llm.messages") question = "What is Eden AI?" result = rag_pipeline.run( { "fetcher": {"urls": ["https://www.edenai.co/"]}, "prompt_builder": { "template_variables": {"query": question}, "template": messages, }, }, ) print(result["llm"]["replies"][0].text)管道连接关系清晰:fetcher.streams → converter.sources、converter.documents → prompt_builder.documents、prompt_builder.prompt → llm.messages。generation_kwargs中可传入 Eden AI 特有的 fallback 模型等参数,API 支持的其他参数详见 Eden AI 官方 API 文档。
输出结构:run()返回字典,键为"replies",值为ChatMessage列表。从基类 openai.py 的示例输出可见,每个 reply 的meta中携带model、index、finish_reason与 token 用量(usage),可用于日志与成本统计。
六、序列化:与 Haystack 管道 YAML/JSON 生态无缝衔接
三个组件均实现to_dict() -> dict[str, Any],返回包含序列化数据的字典,与 Haystack 的default_to_dict机制兼容。这意味着:
- 组件可以嵌入到 Haystack 的管道序列化体系中,通过 YAML/JSON 描述管道结构并整体保存、加载;
api_key以Secret形式序列化,密钥本身不落盘,加载后仍通过环境变量或注入的 Secret 解析;- 配合
from_dict反序列化可还原完整组件实例,便于管道模板复用与版本管理。
七、总结与实践建议
| 场景 | 推荐组件 | 关键参数 |
|---|---|---|
| 文档入库向量化 | EdenAIDocumentEmbedder | model、batch_size、meta_fields_to_embed |
| 查询/短文本编码 | EdenAITextEmbedder | model、prefix/suffix |
| 多模型对话/RAG 生成 | EdenAIChatGenerator | model、tools、streaming_callback、generation_kwargs |
三点实战建议:
- 善用
provider/model命名:切换厂商只需改model字符串,可快速做模型对比实验;Eden AI 的 fallback 能力可通过generation_kwargs启用,提升生产可用性; - 超时与重试优先用环境变量治理:
OPENAI_TIMEOUT、OPENAI_MAX_RETRIES对所有 Eden AI 组件统一生效(默认 30 秒 / 5 次),生产环境按 SLA 统一调整,避免逐组件配置; - 嵌入模型务必两侧一致:索引与查询管道使用同一
model(或至少同一向量空间内的模型),否则语义检索质量无法保证;embedding_separator与meta_fields_to_embed的改动会影响向量语义,变更后建议重建索引。
进一步阅读:三个组件的独立使用指南见 edenaidocumentembedder.mdx、edenaitextembedder.mdx 与 edenaichatgenerator.mdx;底层 OpenAI 兼容客户端的超时/重试/httpx 配置机制可对照基类源码 openai_document_embedder.py 与 openai.py 深入理解。
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考