当前位置: 首页 > news >正文

大模型WebUI:Gradio全解12——使用Agents和Tools智能代理工具构建UI(1)

大模型WebUI:Gradio全解12——使用Agents和Tools智能代理工具构建UI(1)

  • 前言
  • 本篇摘要
  • 12. 使用Agents和Tools智能代理工具构建UI
    • 12.1 transformers.agents原理及示例
      • 12.1.1 代理概念、类型和构建
        • 1. 代理概念
        • 2. 代理类型
        • 3. 如何构建代理?
      • 12.1.2 定义大模型引擎Engines
        • 1. 模型函数:llm_engine
        • 2. TransformersEngine类
        • 3. HfApiEngine类
        • 4. HfEngine
      • 12.1.3 创建和使用工具Tools
        • 1. 默认工具箱
        • 2. 创建新工具
        • 3. 管理代理的工具箱
        • 4. 使用工具集合
      • 12.1.4 系统提示
        • 1. 系统提示示例
        • 2. 系统提示格式
        • 3. 修改系统提示
      • 12.1.5 其它设置
        • 1. 导入代码
        • 2. run的运行参数
        • 3. 检查代理运行情况
      • 12.1.6 使用transformers.agents的构建Gradio UI
        • 1. ChatMessage数据类
        • 2. 构建Gradio UI示例
    • 参考文献

前言

本系列文章主要介绍WEB界面工具Gradio。Gradio是Hugging Face发布的简易WebUI开发框架,它基于FastAPI和svelte,可以使用机器学习模型、python函数或API开发多功能界面,并可部署人工智能模型,是当前热门的非常易于展示机器学习大语言模型LLM及扩散模型DM的WebUI框架。
本系列文章分为五部分:Gradio介绍、HuggingFace资源与工具库、Gradio基础功能实战、Gradio与大模型融合实战和Gradio高级功能实战。第一部分Gradio介绍,包括三章内容:第一章先介绍Gradio的概念,包括详细技术架构、历史、应用场景、与其他框架Gradio/NiceGui/StreamLit/Dash/PyWebIO的区别,然后详细介绍了Gradio的安装与运行,安装包括Linux/Win/Mac三类系统安装,运行包括普通方式和热重载方式;第二章介绍Gradio的4种部署方式,包括本地部署launch()、huggingface托管、FastAPI挂载和Gradio-Lite浏览器集成;第三章介绍Gradio的三种Client,包括python客户端、javascript客户端和curl客户端,方便读者对Gradio整体把握。第二部分介绍著名网站Hugging Face的各类资源和工具库,因为Gradio演示中经常用到Hugging Face的models及某些场景需要部署在spaces,包括两章内容:第四章详解三类资源models/datasets/spaces的使用,第五章实战六类工具库transformers/diffusers/datasets/PEFT/accelerate/optimum实战。第三部分是Gradio基础功能实战,进入本系列文章的核心,包括四章内容:第六章讲解Gradio库的模块架构和环境变量,第七章讲解Gradio高级抽象界面类Interface,第八章讲解Gradio底层区块类Blocks,第九章讲解补充特性Additional Features。第四部分是Gradio与大模型融合的实战,包括三章内容:第十章讲解融合大模型的多模态聊天机器人组件Chatbot,第十一章讲解使用Agents和Tools智能代理工具构建UI,第十二章讲述将Gradio用于LLM Agents的Gradio Tools。第五部分详解Gradio高级功能,包括三章内容:第十三章讲述Discord Bot/Slack Bot/Website Widget部署,第十四章讲述数据科学与绘图Data Science And Plots,第十五章讲述数据流Streaming。
本系列文章讲解细致,涵盖Gradio大部分组件和功能,代码均可运行并附有大量运行截图,方便读者理解并应用到开发中,Gradio一定会成为每个技术人员实现各种奇思妙想的最称手工具。

本系列文章目录如下:

  1. 《Gradio全解1——Gradio简介》
  2. 《Gradio全解1——Gradio的安装与运行》
  3. 《Gradio全解2——Gradio的3+1种部署方式实践》
  4. 《Gradio全解2——浏览器集成Gradio-Lite》
  5. 《Gradio全解3——Gradio Client:python客户端》
  6. 《Gradio全解3——Gradio Client:javascript客户端》
  7. 《Gradio全解3——Gradio Client:curl客户端》
  8. 《Gradio全解4——剖析Hugging Face:详解三类资源models/datasets/spaces》
  9. 《Gradio全解5——剖析Hugging Face:实战六类工具库transformers/diffusers/datasets/PEFT/accelerate/optimum》
  10. 《Gradio全解6——Gradio库的模块架构和环境变量》
  11. 《Gradio全解7——Interface:高级抽象界面类(上)》
  12. 《Gradio全解7——Interface:高级抽象界面类(下)》
  13. 《Gradio全解8——Blocks:底层区块类(上)》
  14. 《Gradio全解8——Blocks:底层区块类(下)》
  15. 《Gradio全解9——Additional Features:补充特性(上)》
  16. 《Gradio全解9——Additional Features:补充特性(下)》
  17. 《Gradio全解10——Chatbot:融合大模型的多模态聊天机器人(1)》
  18. 《Gradio全解10——Chatbot:融合大模型的多模态聊天机器人(2)》
  19. 《Gradio全解10——Chatbot:融合大模型的多模态聊天机器人(3)》
  20. 《Gradio全解10——Chatbot:融合大模型的多模态聊天机器人(4)》
  21. 《Gradio全解10——Chatbot:融合大模型的多模态聊天机器人(5)》
  22. 《Gradio全解11——使用Agents和Tools智能代理工具构建UI(1)》
  23. 《Gradio全解11——使用Agents和Tools智能代理工具构建UI(2)》
  24. 《Gradio全解11——使用Agents和Tools智能代理工具构建UI(3)》
  25. 《Gradio全解11——使用Agents和Tools智能代理工具构建UI(4)》
  26. 《Gradio全解12——Gradio Tools:将Gradio用于LLM Agents》
  27. 《Gradio全解系列13——Discord Bot/Slack Bot/Website Widget部署》
  28. 《Gradio全解系列14——Data Science And Plots:数据科学与绘图》
  29. 《Gradio全解15——Streaming:数据流(上)》
  30. 《Gradio全解15——Streaming:数据流(下)》

本篇摘要

本章介绍如何使用Agents和Tools智能代理工具构建Gradio UI,主要内容包括transformers.agents原理及示例用法、langchain agents的原理及示例用法、langgraph的原理及示例用法和使用显示思考的Gemini 2.0 Flash Thinking API构建UI。

12. 使用Agents和Tools智能代理工具构建UI

Gradio的组件Chatbot原生支持显示中间思考过程和工具使用情况(参考其参数metadata用法),这使得它非常适合为LLM Agent、思维链(Chain-of-Thought, CoT)或推理演示创建用户界面,本章将展示如何使用gr.Chatbot和gr.ChatInterface来显示思考过程和工具使用情况。
本章讲解四种代理和工具方式构建用户界面,其中前三种为代理方式,包括transformers.agents、langchain agents和langgraph,第四种使用显示思考的思维链工具Gemini 2.0 Flash Thinking API构建UI。因为Agents作为连接各大模型和工具的桥梁,是打通人工通用智能(AGI)的最后一公里,对从业者和人工智能行业都是至关重要的一环,所以本章将重点放在Agents智能体的原理及应用步骤拆解,然后才是通过Gradio构建UI。作者为此阅读了大量文献,以尽量阐述清楚智能代理,请读者不吝三连和评论,共同进步变强。

12.1 transformers.agents原理及示例

本节讲述transformers.agents原理及示例,内容包括代理概念类型和构建、定义大模型引擎Engines、创建和使用Tools、系统提示、其它设置和使用transformers.agents构建Gradio UI。

12.1.1 代理概念、类型和构建

本小节讲述代理的概念、类型和构建方法,对理解代理至关重要。

1. 代理概念

经过大量因果语言建模(causal language modeling)训练的大型语言模型(LLMs)能够处理多种任务,但在逻辑、计算和搜索等基本任务上往往表现不佳。当在这些不擅长的领域中被prompt时,大模型通常无法生成我们期望的答案,克服这一弱点的一种方法是创建代理LLM Agent。

LLM Agent的定义非常宽泛:通常指的是所有将LLM作为核心引擎,并能够根据观察对其环境施加影响的系统。这些系统能够通过多次迭代“感知 ⇒ 思考 ⇒ 行动”的循环来实现既定任务,并常常融入规划或知识管理系统以提升其表现效能。并且LLM Agent可以访问工具(Tools),这些工具通常是用于执行任务的函数,它们必须包含代理正确使用它们所需的所有描述。我们可以在论文《The Rise and Potential of Large Language Model Based Agents: A Survey》的研究中找到对智能体领域的精彩评述。

2. 代理类型

代理可以设计为一系列动作/工具(actions/tools)并一次性运行它们,也可以逐个计划后执行动作/工具,并在启动下一个动作之前等待前面每个动作的结果。因此根据代理设计理念的不同,一般分为两种类型:

  1. Code agent:该代理有一个规划步骤,然后生成Python代码以一次性执行所有动作。它原生支持处理工具内不同的输入和输出类型,因此是多模态任务的推荐选择;
  2. React agent:它采用一种基于“推理 (Reasoning)”与“行动 (Acting)”结合的方式逐步解决给定任务,并以此来构建智能体。Transformers实现了三种版本的React agent:
    (1)ReactAgent:原始的推理执行代理,它的行动将从大语言模型(LLM)的输出中解析出来,它并不常用,经常会被下面两种衍生代理代替;
    (2)ReactJsonAgent:工具调用将由LLM以JSON代码块生成,然后解析并执行;
    (3)ReactCodeAgent:是一种新型的ReactJsonAgent,工具调用将由LLM以Python代码块生成,这对于具有强大编码性能的LLM非常有效。

我们将重点放在ReAct智能体上,因为它是解决推理任务的首选代理。在提示词中,我们阐述了模型能够利用哪些工具,并引导它逐步思考“step by step” (亦称为思维链行为Chain-of-Thought),以规划并实施其后续动作。ReAct框架(ReAct: Synergizing Reasoning and Acting in Language Models)使代理可以在基于先前观察的基础上进行多次非常高效的思考。读者可以阅读Open-source LLMs as LangChain Agents博客文章(https://huggingface.co/blog/open-source-llms-as-agents)以了解更多关于使用ReAct代理的信息。

单步Code agent与多步React agent执行流程区别可参考下图:
在这里插入图片描述

3. 如何构建代理?

要初始化一个代理,需要以下参数:

  1. llm_engine:此参数设置为代理提供动力引擎的LLM,代理并不完全是LLM,它更像是一个使用LLM作为引擎的程序;
  2. 工具箱:代理从中挑选工具来执行任务;
  3. 系统提示(system prompt):LLM引擎将根据这个提示生成其输出;
  4. 解析器:用于从LLM的输出中提取需要调用的工具及其参数。

在代理系统初始化时,工具的属性被用来生成工具描述,将其嵌入到代理的system_prompt中,以便代理知道它可以使用哪些工具以及为什么使用这些工具。然后LLM根据系统提示输出解决方案,解析器解析LLM的输出后,决定调用哪些工具继续执行。最后当已经得到答案或者满足停止条件将结束会话,否则继续迭代执行。下面对这四方面内容逐一讲述。当然开始之前,请使用以下命令额外安装transformers的agents以安装所有默认依赖项:pip install transformers[agents]。

12.1.2 定义大模型引擎Engines

我们可以自由创建和使用用于代理框架的引擎Engines,但需要满足以下条件:

  • 它遵循输入消息的消息格式(List[Dict[str, str]]),并返回一个字符串;
  • 它在传入的参数stop_sequences指定的序列处停止生成输出。

下面就来了解下四种不同的创建引擎方法:模型函数llm_engine、TransformersEngine、HfApiEngine和HfEngine,请注意区分它们适用的场景。

1. 模型函数:llm_engine

我们可以通过定义一个接受消息列表并返回文本的函数llm_engine来构建LLM引擎,这个可调用对象还需要接受一个stop参数以指示何时停止生成。

from huggingface_hub import login, InferenceClientlogin("<YOUR_HUGGINGFACEHUB_API_TOKEN>")client = InferenceClient(model="meta-llama/Meta-Llama-3-70B-Instruct")def llm_engine(messages, stop_sequences=["Task"]) -> str:response = client.chat_completion(messages, stop=stop_sequences, max_tokens=1000)answer = response.choices[0].message.contentreturn answer

此外,llm_engine还可以接受一个grammar参数。如果在代理初始化时指定了grammar,这个参数将连同初始化时定义的grammar一起传递给llm_engine的调用,以实现受约束的生成,从而强制代理生成格式正确的输出。

2. TransformersEngine类

为了方便起见,我们可以添加一个TransformersEngine,它通过预初始化的Pipeline作为输入实现上述功能,或可选的使用model_id,以便使用transformers在本地机器上运行推理。示例代码如下:

from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline, TransformersEnginemodel_name = "HuggingFaceTB/SmolLM-135M-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
engine = TransformersEngine(pipe)
engine([{"role": "user", "content": "Ok!"}], stop_sequences=["great"])
# 输出
"What a "
3. HfApiEngine类

由于代理行为通常需要更强的模型,如Llama-3.1-70B-Instruct,这些模型目前较难在本地运行,因此我们还提供了HfApiEngine类,HfApiEngine是一个封装了Hugging Face Inference API客户端的引擎,即在底层初始化了一个huggingface_hub.InferenceClient,用于执行大语言模型(LLM)的调用。

该引擎通过Hugging Face的推理API与语言模型进行通信,它可以在无服务器模式(serverless)下使用,也可以与专用端点(dedicated endpoint)一起使用,并支持诸如停止序列(stop sequences)和语法自定义(grammar customization)等功能。程序中甚至可以留空llm_engine参数,默认情况下会创建一个HfApiEngine。示例代码如下:

from transformers import HfApiEnginellm_engine = HfApiEngine(model="meta-llama/Meta-Llama-3-70B-Instruct")
4. HfEngine

对于本地部署的具有Inference API的LLM,我们还可以直接使用包中提供的 HfEngine 类来获取一个调用我们自己的Inference API的LLM引擎,示例代码如下:

from transformers.agents import HfEnginellm_engine = HfEngine("meta-llama/Meta-Llama-3-70B-Instruct")

12.1.3 创建和使用工具Tools

工具是代理使用的原子函数,包括各种属性和执行方法。例如PythonInterpreterTool:它有一个名称、描述、输入描述、输出类型,以及一个执行操作的 call 方法。当代理初始化时,工具属性会被用来生成工具描述,并将其嵌入到代理的系统提示中,这让代理知道它可以使用哪些工具以及为什么使用这些工具。工具是代理的核心部分,工具的好坏和数量决定了代理能力的大小。本节将从默认工具箱、创建新工具、管理工具箱及使用工具集等方面讲解如何使用工具。

1. 默认工具箱

Transformers附带了一个默认工具箱,用于增强代理的功能。构建Agent时需要一个tools参数,它接受一个工具列表(List[Tools])——这个列表可以是空的,但可以在代理初始化时,通过定义可选参数add_base_tools=True,将默认工具箱添加到工具列表。默认工具箱中工具如下:

  • 文档问答:给定一个图像格式的文档(如PDF),回答关于该文档的问题(Donut);
  • 图像问答:给定一张图像,回答关于该图像的问题(VILT);
  • 语音转文本:给定一段人声录音,将语音转录为文本(Whisper);
  • 文本转语音:将文本转换为语音(SpeechT5);
  • 翻译:将给定的句子从源语言翻译为目标语言;
  • DuckDuckGo搜索*:使用DuckDuckGo浏览器执行网络搜索;
  • Python代码解释器:在安全环境中运行由LLM生成的Python代码。此工具仅在初始化 ReactJsonAgent时通过add_base_tools=True添加,因为基于代码的代理已经可以原生执行Python代码。

我们还可以通过调用load_tool()函数并指定要执行的任务来手动使用工具,示例代码如下:

from transformers import load_tooltool = load_tool("text-to-speech")
audio = tool("This is a text to speech tool")
2. 创建新工具

我们可以为Hugging Face默认工具未涵盖的用例创建自己的工具。以返回HF Hub上某个任务下载量最多的模型为例创建一个工具,步骤如下:

  1. 创建核心功能代码:
from huggingface_hub import list_modelstask = "text-classification"model = next(iter(list_models(filter=task, sort="downloads", direction=-1)))
print(model.id)
  1. 然后将核心代码封装为工具函数以快速将其转换为工具,操作时只需将其包装在一个函数中并添加工具装饰器@tool即可:
from transformers import tool@tool
def model_download_tool(task: str) -> str:"""This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub.It returns the name of the checkpoint.Args:task: The task for which"""model = next(iter(list_models(filter="text-classification", sort="downloads", direction=-1)))return model.id

此函数需要:

  • 清晰的函数名:名称通常描述工具的功能,由于代码返回某个任务下载量最多的模型,我们可以命名为model_download_tool;
  • 输入和输出的类型提示:输入的类型提示为函数的入参,输出类型提示为符号->后的类型,方便大模型调用;
  • 函数描述:描述函数的作用和返回说明,其中包括一个“Args:”部分,描述每个参数的作用(注意这里不需要类型指示,因为会从类型提示中提取)。所有这些将在初始化时自动嵌入到代理的系统提示中,因此请尽量使它们清晰易懂!
  1. 最后将工具直接添加到初始化代理的参数tools中。现在,我们可以创建一个代理,比如CodeAgent,并使用创建的工具model_download_tool,示例代码如下:
from transformers import CodeAgent, HfApiEnginellm_engine = HfApiEngine(model="meta-llama/Meta-Llama-3-70B-Instruct")
agent = CodeAgent(tools=[model_download_tool], llm_engine=llm_engine)
agent.run("Can you give me the name of the model that has the most downloads in the 'text-to-video' task on the Hugging Face Hub?"
)

运行后得到以下输出:

======== New task ========
Can you give me the name of the model that has the most downloads in the 'text-to-video' task on the Hugging Face Hub?
==== Agent is executing the code below:
most_downloaded_model = model_download_tool(task="text-to-video")
print(f"The most downloaded model for the 'text-to-video' task is {most_downloaded_model}.")
==== The output: 
"The most downloaded model for the 'text-to-video' task is ByteDance/AnimateDiff-Lightning."
3. 管理代理的工具箱

当我们已经初始化了一个带有工具箱的代理时,从头开始重新初始化以添加想使用的工具会很不方便。此时可以使用Transformers代理,通过toolbox中函数add_tool()和update_tool()来添加或替换工具来管理代理的工具箱。

让我们将上面定义的model_download_tool添加到一个仅使用默认工具箱初始化的现有代理中,代码如下:

from transformers import CodeAgentagent = CodeAgent(tools=[], llm_engine=llm_engine, add_base_tools=True)
agent.toolbox.add_tool(model_download_tool)

现在我们可以同时利用新工具和之前的文本转语音工具:

agent.run("Can you read out loud the name of the model that has the most downloads in the 'text-to-video' task on the Hugging Face Hub and return the audio?"
)

在为已经运行良好的代理添加工具时要小心,因为它可能会偏向选择你定义的工具,或者选择与原工具不同的工具。

我们还可以使用方法agent.toolbox.update_tool()替换代理工具箱中的现有工具,尤其是新工具一对一替换现有工具时将非常有用,因为代理已经知道如何执行该特定任务。替换时只需确保新工具遵循与被替换工具相同的API,或者调整系统提示模板以确保更新所有使用被替换工具的示例。

4. 使用工具集合

我们还可以通过使用transformers中的对象ToolCollection来利用工具集合,并通过参数collection_slug指定想要使用的集合片,它们将作为列表传递给代理进行初始化,示例代码如下:

from transformers import ToolCollection, ReactCodeAgentimage_tool_collection = ToolCollection(collection_slug="huggingface-tools/diffusion-tools-6630bb19a942c2306a2cdb6f")
agent = ReactCodeAgent(tools=[*image_tool_collection.tools], add_base_tools=True)agent.run("Please draw me a picture of rivers and lakes.")

为了加快启动速度,工具只有在被代理调用时才会加载。另外,实际运行时可能会报错:ImportError: cannot import name ‘cached_download’ from ‘huggingface_hub’. Did you mean: ‘hf_hub_download’?。原因可能是工具内部调用有问题,只能等官方更新。运行正常时,上面代码将会产生以下类似图片:
在这里插入图片描述

12.1.4 系统提示

在代理系统初始化时,工具的属性被用来生成工具描述,将其嵌入到代理的system_prompt中,以便代理知道它可以使用哪些工具以及为什么使用这些工具,然后LLM根据系统提示输出解决方案。本小节将展示系统提示示例、解析系统提示格式以及如何修改系统提示。

1. 系统提示示例

系统提示(system prompt)和输出解析器(output parser)是自动定义的,但我们可以通过调用代理上的system_prompt_template和tool_parser轻松查看它们。

代理,或者更准确地说,驱动代理的LLM,会根据系统提示生成输出。系统提示可以根据预期的任务进行定制和调整。在系统提示中,尽可能清楚地解释我们想要执行的任务非常重要。由于代理是由LLM驱动的,且每次run()操作都是独立的,提示中的微小变化可能会产生完全不同的结果,因此也可以连续运行代理以执行不同的任务:每次运行时,agent.task和agent.logs属性都会重新初始化。

例如,查看ReactCodeAgent的系统提示(以下版本略有简化):

>>> print(agent.system_prompt_template)
>>> You will be given a task to solve as best you can.
You have access to the following tools:
<<tool_descriptions>>To solve the task, you must plan forward to proceed in a series of steps, in a cycle of 'Thought:', 'Code:', and 'Observation:' sequences.At each step, in the 'Thought:' sequence, you should first explain your reasoning towards solving the task, then the tools that you want to use.
Then in the 'Code:' sequence, you should write the code in simple Python. The code sequence must end with '/End code' sequence.
During each intermediate step, you can use 'print()' to save whatever important information you will then need.
These print outputs will then be available in the 'Observation:' field, for using this information as input for the next step.In the end you have to return a final answer using the `final_answer` tool.Here are a few examples using notional tools:
---
{examples}Above example were using notional tools that might not exist for you. You only have acces to those tools:
<<tool_names>>
You also can perform computations in the python code you generate.Always provide a 'Thought:' and a 'Code:\n```py' sequence ending with '```<end_code>' sequence. You MUST provide at least the 'Code:' sequence to move forward.Remember to not perform too many operations in a single code block! You should split the task into intermediate code blocks.
Print results at the end of each step to save the intermediate results. Then use final_answer() to return the final result.Remember to make sure that variables you use are all defined.Now Begin!
2. 系统提示格式

观察上面系统提示示例,可以发现系统提示一般包括:

  • 一段介绍,解释代理应如何行为以及工具是什么;
  • 所有工具的描述,这些描述由<<tool_descriptions>>标记定义,该标记在运行时动态替换为用户定义/选择的工具,工具描述来源于工具属性,包括名称、描述、输入和输出类型,以及一个用户可以优化的简单jinja2模板;
  • 示例examples,示例中尽量包含所提到的工具及使用方法;
  • 预期的输出格式,对final_answer的具体要求。

系统提示格式只是起到引导作用,并没有具体的格式规定,可根据自己需求添加或删除,但一般情况是:越具体越清晰的系统提示会产生更好的输出效果!

3. 修改系统提示

我们可以改进系统提示,例如通过添加对输出格式的解释以强制产生需要的输出。为了获得最大的灵活性,甚至可以通过将自定义提示作为参数传递给system_prompt参数来覆盖整个系统提示模板。具体操作时,可通过agent.system_prompt_template获取初始化的系统提示,根据自己需要修改后进行替换,替换代码如下:

from transformers import ReactJsonAgent
from transformers.agents import PythonInterpreterToolagent = ReactJsonAgent(tools=[PythonInterpreterTool()], system_prompt="{your_custom_prompt}")

请确保在模板中的某个位置定义<<tool_descriptions>>字符串,以便代理知道可用的工具。

12.1.5 其它设置

除了引擎、工具和系统提示外,还有一些辅助设置,可以帮助我们更好的使用代理,比如对于CodeAgent、ReactCodeAgent,在执行生成代码时,可能需要导入某些运行库;或者agent运行时需添加句子、文件等可替换参数;当代理运行完毕后查看代理的运行情况等,下面逐一讲述。

1. 导入代码

Python解释器会在一组与工具一起传递的输入上执行代码,这应该是安全的,因为解释器只能调用传入的工具函数(特别是Hugging Face工具)和print函数,因此这里已经限制了可以执行的内容。

默认情况下,Python解释器也不允许在安全列表之外进行导入,因此所有最明显的攻击都不应该成为问题。但我们仍然可以通过在初始化ReactCodeAgent或CodeAgent时,将授权的模块作为字符串列表传递给additional_authorized_imports参数来授权额外的导入,示例如下:

from transformers import ReactCodeAgentagent = ReactCodeAgent(tools=[], additional_authorized_imports=['requests', 'bs4'])agent.run("Could you get me the title of the page at url 'https://huggingface.co/blog'?")(...)
'Hugging Face – Blog'

python解释器会在尝试执行任何非法操作的代码处停止,或者当代理生成的代码存在常规的Python错误时也会停止。LLM可以生成任意代码后执行,但请注意,不要添加任何不安全的导入!

2. run的运行参数

当代理调用方法run()时,可以添加额外的参数,比如参数sentence可以将文本作为额外参数传递给模型,示例如下:

from transformers import CodeAgent, HfApiEnginellm_engine = HfApiEngine(model="meta-llama/Meta-Llama-3-70B-Instruct")
agent = CodeAgent(tools=[], llm_engine=llm_engine, add_base_tools=True)agent.run("Could you translate this sentence from French, say it out loud and return the audio.",sentence="Où est la boulangerie la plus proche?",
)

另外,也可以使用这个参数来指示模型使用的本地或远程文件的路径,如下::

from transformers import ReactCodeAgentagent = ReactCodeAgent(tools=[], llm_engine=llm_engine, add_base_tools=True)agent.run("Why does Mike not know many people in New York?", audio="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/recording.mp3")
3. 检查代理运行情况

当代理成功运行后,可以通过一些有用的属性检查运行后发生的情况:agent.logs 存储了代理的详细日志。在代理运行的每一步,所有内容都会被存储在一个字典中,然后追加到agent.logs中。

运行agent.write_inner_memory_from_logs() 会为代理的日志创建一个内部记忆,化作聊天消息列表供LLM查看。此方法会遍历日志的每一步,并仅将其感兴趣的内容存储为消息:例如,它会将系统提示和任务保存在不同的消息中,然后对于每一步,它会将LLM输出存储为一条消息,工具调用输出存储为另一条消息。如果我们想在更高层次的视角来了解发生了什么,可以使用这个方法——但并非所有日志都会被此方法转录。

为方便理解ReAct流程,可以参考下面ReactCodeAgent解决问题时的执行步骤:

agent.run("How many more blocks (also denoted as layers) in BERT base encoder than the encoder from the architecture proposed in Attention is All You Need?",
)=====New task=====
How many more blocks (also denoted as layers) in BERT base encoder than the encoder from the architecture proposed in Attention is All You Need?====Agent is executing the code below:
bert_blocks = search(query="number of blocks in BERT base encoder")
print("BERT blocks:", bert_blocks)
====
Print outputs:
BERT blocks: twelve encoder blocks====Agent is executing the code below:
attention_layer = search(query="number of layers in Attention is All You Need")
print("Attention layers:", attention_layer)
====
Print outputs:
Attention layers: Encoder: The encoder is composed of a stack of N = 6 identical layers. Each layer has two sub-layers. The first is a multi-head self-attention mechanism, and the second is a simple, position- 2 Page 3 Figure 1: The Transformer - model architecture.====Agent is executing the code below:
bert_blocks = 12
attention_layers = 6
diff = bert_blocks - attention_layers
print("Difference in blocks:", diff)
final_answer(diff)
====
Print outputs:
Difference in blocks: 6Final answer: 6

12.1.6 使用transformers.agents的构建Gradio UI

在用transformers.agents的构建Gradio UI之前,先回顾下Gradio的数据类ChatMessage,然后使用ChatMessage构建UI。

1. ChatMessage数据类

在Gradio的聊天机器人chatbot中,每条消息都是一个类型为ChatMessage的数据类(假设聊天机器人的type=“message”,推荐使用此类型,因为tuple类型即将被废弃)。ChatMessage及其子类MetadataDict、OptionDict的结构如下:

@dataclass
class ChatMessage:content: str | Componentrole: Literal["user", "assistant"]metadata: MetadataDict = Noneoptions: list[OptionDict] = Noneclass MetadataDict(TypedDict):title: NotRequired[str]id: NotRequired[int | str]parent_id: NotRequired[int | str]log: NotRequired[str]duration: NotRequired[float]status: NotRequired[Literal["pending", "done"]]class OptionDict(TypedDict):label: NotRequired[str]value: str

对于我们的需求来说,最重要的键是metadata键,它接受一个字典MetadataDict。如果这个字典中包含消息的标题(title),它将会显示在一个可折叠的框中,代表一个“思考”。就是这么简单,看看这个例子:

import gradio as grwith gr.Blocks() as demo:chatbot = gr.Chatbot(type="messages",value=[gr.ChatMessage(role="user", content="What is the weather in San Francisco?"),gr.ChatMessage(role="assistant", content="I need to use the weather API tool?",metadata={"title":  "🧠 Thinking"}])demo.launch()

运行截图参照上一章内容。除了title之外,提供给metadata的字典还可以包含以下几个可选键:

  • log:一个可选的字符串值,会以较淡的字体显示在思考标题旁边;
  • duration:一个可选的数值,表示思考/工具使用的持续时间(以秒为单位),会以较淡的字体显示在思考标题旁边的括号内;
  • status:如果设置为pending,会在思考标题旁边显示一个加载动画;如果设置为done,思考的可折叠框会关闭;如果未提供,思考的可折叠框会默认打开且不显示加载动画;
  • id和parent_id:如果提供了这些键,可以用来将思考嵌套在其他思考中。

下面,我们展示了一个完整的示例,演示如何使用gr.Chatbot和gr.ChatInterface来展示工具使用或思考的用户界面。

2. 构建Gradio UI示例

我们将创建一个简单的Gradio应用程序代理,该代理可以使用文本生成图像的工具。提示:请确保先理解了前面内容或阅读了transformers.agents文档,地址:https://huggingface.co/docs/transformers/en/agents。

我们将从导入transformers和gradio中的必要类开始,代码如下:

import gradio as gr
from dataclasses import asdict
from transformers import Tool, ReactCodeAgent  # type: ignore
from transformers.agents import stream_to_gradio, HfApiEngine  # type: ignore# Import tool from Hub
image_generation_tool = Tool.from_space(  # type: ignorespace_id="black-forest-labs/FLUX.1-schnell",name="image_generator",description="Generates an image following your prompt. Returns a PIL Image.",api_name="/infer",
)llm_engine = HfApiEngine("Qwen/Qwen2.5-Coder-32B-Instruct")
# Initialize the agent with both tools and engine
agent = ReactCodeAgent(tools=[image_generation_tool], llm_engine=llm_engine)# Building UI
def interact_with_agent(prompt, history):messages = []yield messagesfor msg in stream_to_gradio(agent, prompt):messages.append(asdict(msg))  # type: ignoreyield messagesyield messagesdemo = gr.ChatInterface(interact_with_agent,chatbot= gr.Chatbot(label="Agent",type="messages",avatar_images=(None,"https://em-content.zobj.net/source/twitter/53/robot-face_1f916.png",),),examples=[["Generate an image of an astronaut riding an alligator"],["I am writing a children's book for my daughter. Can you help me with some illustrations?"],],type="messages",
)if __name__ == "__main__":demo.launch()

运行截图如下:
在这里插入图片描述
作者在本地运行时会报JSON解析错误:JSONDecodeError: Expecting value: line 1 column 1 (char 0),解决办法无从查找,可能和使用VPN代理环境有关。读者可以将代码复制到Google Colab上运行,也可以直接通过Hugging Face的演示查看效果:https://huggingface.co/spaces/gradio/agent_chatbot。
从输出可以看到思考、工具调用和输出结果的调用过程,正是ReactCodeAgent代理的推理执行过程。

参考文献

  1. Gradio - guides - Chatbots
  2. License to Call: Introducing Transformers Agents 2.0
  3. Hugging Face - Transformers - Agents and tools

http://www.mrgr.cn/news/90671.html

相关文章:

  • 本地DataGrip连接Linux服务器中MySQL失败处理方法
  • 国产数据库有哪些?介绍下他们的名字、作者、成熟度、适用的应用场景、不足。
  • RAGFlow和Dify对比
  • 19.4.6 读写数据库中的二进制数据
  • 【竞技宝】PGL瓦拉几亚S4预选:Tidebound2-0轻取spiky
  • 如何在24GB的GPU上运行DeepSeek-R1-Distill-Qwen-32B
  • 系统URL整合系列【不改hosts文件版】-- 代码1(springcloud-gateway动态路由)
  • 教程 | Proxmox VE(PVE)安装全流程指南(末尾附镜像及快速配置脚本)
  • 250213-异常exception
  • 【鸿蒙】ArkUI-X跨平台问题集锦
  • Elasticvue使用总结
  • Navicat导入海量Excel数据到数据库(简易介绍)
  • Linux——stdio
  • CentOS 7操作系统部署KVM软件和创建虚拟机
  • JavaScript 发起网络请求
  • DeepSeek教unity------MessagePack-01
  • 【2025深度学习系列专栏大纲:深入探索与实践深度学习】
  • PostgreSQL 备库的延迟问题
  • AcWing 795. 前缀和理解
  • 微服务SpringCloud Alibaba组件nacos教程(一)【详解naocs基础使用、服务中心配置、集群配置,附有案例+示例代码】
  • 【OpenCV】双目相机计算深度图和点云
  • windows10本地的JMeter+Influxdb+Grafana压测性能测试,【亲测,避坑】
  • MySQL、MariaDB 和 TDSQL 的区别
  • dedecms 开放重定向漏洞(附脚本)(CVE-2024-57241)
  • post、get、delete、put请求
  • 如何部署Deepseek-R1:从零开始的完整指南