⭐️ Highlights
工具调用支持
我们引入了 Tool,这是一个简单统一的抽象,用于在 Haystack 中表示工具,以及 ToolInvoker,用于执行由 LLM 准备的工具调用。这些功能可以轻松地将工具调用集成到您的 Haystack 管道中,从而在与 OpenAIChatGenerator 和 HuggingFaceAPIChatGenerator 等组件一起使用时,实现与工具的无缝交互。以下是如何使用它们:
def dummy_weather_function(city: str):
return f"The weather in {city} is 20 degrees."
tool = Tool(
name="weather_tool",
description="A tool to get the weather",
function=dummy_weather_function,
parameters={
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
}
)
pipeline = Pipeline()
pipeline.add_component("llm", OpenAIChatGenerator(model="gpt-4o-mini", tools=[tool]))
pipeline.add_component("tool_invoker", ToolInvoker(tools=[tool]))
pipeline.connect("llm.replies", "tool_invoker.messages")
message = ChatMessage.from_user("How is the weather in Berlin today?")
result = pipeline.run({"llm": {"messages": [message]}})
将组件用作工具 作为 Tool 的抽象,ComponentTool 允许 LLM 直接与 Web 搜索、文档处理或自定义用户组件等组件进行交互。它简化了模式生成和类型转换,使得向 LLM 公开复杂的组件功能变得容易。
# Create a tool from the component
tool = ComponentTool(
component=SerperDevWebSearch(api_key=Secret.from_env_var("SERPERDEV_API_KEY"), top_k=3),
name="web_search", # Optional: defaults to "serper_dev_web_search"
description="Search the web for current information on any topic" # Optional: defaults to component docstring
)
新的拆分方法:RecursiveDocumentSplitter
RecursiveDocumentSplitter 引入了一种更智能的文本拆分方法。它使用一组分隔符递归地分割文本,从第一个分隔符开始。如果块仍然大于指定大小,拆分器将移动到列表中的下一个分隔符。这种方法可确保高效且精细的文本拆分,以改进处理。
from haystack.components.preprocessors import RecursiveDocumentSplitter
splitter = RecursiveDocumentSplitter(split_length=260, split_overlap=0, separators=["\n\n", "\n", ".", " "])
doc_chunks = splitter.run([Document(content="...")])
⚠️ 重构了 ChatMessage 数据类
ChatMessage 数据类已被重构,以提高灵活性和兼容性。作为此更新的一部分,已删除 content 属性,并用新的 text 属性替换,用于访问 ChatMessage 的文本值。此更改可确保未来兼容性,并更好地支持工具调用及其结果等功能。有关新 API 和迁移步骤的详细信息,请参阅 ChatMessage 文档。如果您对此重构有任何疑问,请随时在 此 Github discussion 中告诉我们。
⬆️ 升级说明
- 对
ChatMessage数据类的重构包含一些涉及ChatMessage创建和访问属性的重大更改。如果您的Pipeline包含一个ChatPromptBuilder,并且使用haystack-ai =< 2.9.0进行序列化,则反序列化可能会失败。有关更改的详细信息以及如何迁移,请参阅 ChatMessage 文档。 - 已从
PyPDFToDocument中移除已弃用的converterinit 参数。请改用其他 init 参数,或创建自定义组件。 SentenceWindowRetriever的输出键context_documents现在输出一个List[Document],其中包含按split_idx_start排序的检索到的文档和上下文窗口。- 将转换器中的
store_full_path默认值更新为False
🚀 新功能
-
引入了
ComponentTool,这是一个包装 Haystack 组件的新工具,允许它们被用作 LLM(各种 ChatGenerators)的工具。此ComponentTool支持自动工具模式生成、输入类型转换,并支持具有运行方法的组件,这些方法具有输入类型- 基本类型(str、int、float、bool、dict)
- 数据类(简单结构和嵌套结构)
- 基本类型列表(例如,
List[str]) - 数据类列表(例如,
List[Document]) - 混合类型参数(例如,
List[Document]、str 等)
示例用法
from haystack import component, Pipeline from haystack.tools import ComponentTool from haystack.components.websearch import SerperDevWebSearch from haystack.utils import Secret from haystack.components.tools.tool_invoker import ToolInvoker from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage # Create a SerperDev search component search = SerperDevWebSearch(api_key=Secret.from_env_var("SERPERDEV_API_KEY"), top_k=3) # Create a tool from the component tool = ComponentTool( component=search, name="web_search", # Optional: defaults to "serper_dev_web_search" description="Search the web for current information on any topic" # Optional: defaults to component docstring ) # Create pipeline with OpenAIChatGenerator and ToolInvoker pipeline = Pipeline() pipeline.add_component("llm", OpenAIChatGenerator(model="gpt-4o-mini", tools=[tool])) pipeline.add_component("tool_invoker", ToolInvoker(tools=[tool])) # Connect components pipeline.connect("llm.replies", "tool_invoker.messages") message = ChatMessage.from_user("Use the web search tool to find information about Nikola Tesla") # Run pipeline result = pipeline.run({"llm": {"messages": [message]}}) print(result) -
添加
XLSXToDocument转换器,它使用 Pandas + openpyxl 加载 Excel 文件,并默认将每个工作表转换为 CSV 格式的单独Document。 -
已向
PyPDFToDocument和AzureOCRDocumentConverter的__init__方法添加了新的store_full_path参数。默认值为True,它将完整文件路径存储在输出文档的元数据中。当设置为False时,仅存储文件名。 -
添加了一个新的实验性组件
ToolInvoker。此组件根据语言模型准备的工具调用来调用工具,并将结果作为ChatMessage对象列表返回,其中包含工具角色。 -
添加了
RecursiveSplitter,它使用一组分隔符来递归拆分文本。它尝试使用第一个分隔符来分割文本,如果生成的块仍然大于指定大小,它将移至列表中的下一个分隔符。 -
添加了一个
create_tool_from_function函数,用于从函数创建Too实例,自动生成名称、描述和参数。添加了一个tool装饰器以实现相同的结果。 -
为 Hugging Face API Chat Generator 添加了对工具的支持。
-
更改了
ChatMessage数据类,以支持不同类型的内容,包括工具调用和工具调用结果。 -
为 OpenAI Chat Generator 添加了对工具的支持。
-
添加了一个新的
Tool数据类,用于表示语言模型可以为其准备调用的工具。 -
添加了
StringJoiner组件,用于将来自不同组件的字符串连接到字符串列表中。
⚡️ 增强说明
-
为
AzureOpenAIDocumentEmbedder和AzureOpenAITextEmbedder添加了default_headers参数。 -
添加了
token参数到NamedEntityExtractor,以允许使用私有的 Hugging Face 模型。 -
向
ChatMessage类添加了from_openai_dict_format类方法。它允许您从 OpenAI Chat API 期望格式的字典创建ChatMessage。 -
添加了一个测试作业,以检查所有包是否都可以成功导入。这应该有助于检测各种问题,例如忘记为来自惰性导入的类型提示使用前向引用。
-
DocumentJoiner方法_concatenate()和_distribution_based_rank_fusion()已转换为静态方法。 -
改进了可调用对象的序列化和反序列化。我们现在允许序列化类方法和静态方法,并明确禁止序列化实例方法、lambda 函数和嵌套函数。
-
向
PyPDFToDocument组件添加了新的初始化参数,以自定义从 PDF 文件中提取文本的过程。 -
重新组织了文档存储测试套件,以隔离
dataframe过滤器测试。此更改为将来可能弃用 Document 类的dataframe字段做准备。 -
将
Tool移至新的专用tools包。重构了Tool的序列化和反序列化,使其更灵活并包含类型信息。 -
NLTKDocumentSplitter已合并到DocumentSplitter中,后者现在提供与NLTKDocumentSplitter相同的功能。split_by="sentence"现在使用基于nltk库的自定义句子边界检测。之前的sentence行为仍然可以通过split_by="period"来实现。 -
通过使用
importlib而非sys.modules改进了可调用对象的反序列化。此更改允许在反序列化可调用对象时导入不在sys.modules中的本地函数和类。 -
更改
OpenAIDocumentEmbedder以便在批处理嵌入失败时保持运行。现在 OpenAI 会返回一个错误,我们记录该错误并继续处理后续批次。
⚠️ 弃用说明
-
NLTKDocumentSplitter将被弃用,并将在下一个版本中移除。DocumentSplitter将支持NLTKDocumentSplitter的功能。 -
函数角色和
ChatMessage.from_function类方法已被弃用,并将在 Haystack 2.10.0 中移除。ChatMessage.from_function还尝试生成一个有效的工具消息。有关更多信息,请参阅文档:https://docs.haystack.com.cn/docs/chatmessage -
SentenceWindowRetriever的context_documents输出已更改。它不再是List[List[Document],而是List[Document],其中文档按split_idx_start值排序。
🐛 Bug 修复
-
为
LinkContentFetcher的单 URL 场景添加了缺失的流 MIME 类型分配。 -
以前,使用
FileTypeRouter的管道在接收单个 URL 作为输入时可能会失败。 -
OpenAIChatGenerator 在未提供工具时不再将工具传递给 OpenAI 客户端。以前传递的是 null 值。此更改提高了与不支持工具的 OpenAI 兼容 API 的兼容性。
-
ByteStream 现在会将数据截断为 100 字节以避免过多的日志输出。
-
使 HuggingFaceLocalChatGenerator 与新的 ChatMessage 格式兼容,方法是将消息转换为 HuggingFace 所需的格式。
-
序列化
chat_template参数。 -
将 NLTK 的下载移至
DocumentSplitter和NLTKDocumentSplitter的warm_up()。这可以防止在实例化过程中调用外部 API。如果在管道外使用DocumentSplitter或NLTKDocumentSplitter进行句子拆分,现在需要在运行组件之前调用warm_up()。 -
PDFMinerToDocument现在会创建具有基于转换文本和元数据的id的文档。在此之前,PDFMinerToDocument在生成文档的id时未考虑文档的 meta 字段。 -
将 OpenAI 客户端固定到 >=1.56.1,以避免与 httpx 库更改相关的问题。
-
PyPDFToDocument现在会创建具有基于转换文本和元数据的 id 的文档。在此之前,它没有考虑元数据。 -
修复了多线程环境中组件反序列化的问题。
