《开源大模型食用指南》实战:Lagent + InternLM-Chat-7B-V1.1 搭建 ReAct 智能体 Web Demo
2026/9/12 2:07:16 网站建设 项目流程

《开源大模型食用指南》实战:Lagent + InternLM-Chat-7B-V1.1 搭建 ReAct 智能体 Web Demo

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

本文以《开源大模型食用指南》仓库中的 04-Lagent+InternLM-Chat-7B-V1.1.md 为主体,完整讲解如何在 AutoDL 上基于 ModelScope 下载 InternLM-Chat-7B-V1.1 模型、源码安装 Lagent 智能体框架,并运行一个支持 ReAct 推理与 Python 代码执行的 Streamlit Web Demo。读完本文,你将掌握"大模型 + 工具调用"的智能体搭建全流程,并理解 Lagent 中 ReAct Agent、ActionExecutor 与 PythonInterpreter 插件之间的协作关系。

为什么需要 Lagent:让 InternLM 学会"动手解题"

在 01-InternLM-Chat-7B Transformers 部署调用.md 中,我们完成了 InternLM-Chat-7B 的推理调用,但纯 LLM 只能"说话"不能"动手"——遇到2x+3=10这类需要精确计算的问题时,语言模型只能给出文字推导。Lagent(Lightweight Agent)正是上海人工智能实验室开源的大模型智能体框架,从 06-InternLM接入LangChain搭建知识库助手.md 的语料来源可以看到,它与 InternLM、lmdeploy、xtuner 等共同构成了书生系大模型的工具生态。Lagent 的核心思路是:让模型先生成"思考步骤"(thought),再决定调用哪个工具(action),最后根据工具返回结果组织回答——这就是经典的 ReAct(Reasoning + Acting)范式。

本文使用的 Web Demo 代码将 InternLM-Chat-7B-V1.1 作为推理大脑,通过 Lagent 调度 Python 代码解释器插件,把"解方程"这类数学问题交给代码执行解决,最终在浏览器中呈现"模型写代码 → 代码执行 → 返回答案"的完整链路。

环境准备:与 InternLM-Chat-7B 保持一致

本文选择与第一个 InternLM 教程(01-InternLM-Chat-7B Transformers 部署调用.md)相同的 AutoDL 镜像环境:pytorch1.11.03.8(ubuntu20.04)11.3,建议租用 3090 等 24G 显存机器。如果上一个 InternLM-Chat-7B 教程已经配置好环境,则不需要重复安装依赖,可直接跳过本节。

若从零开始,在终端依次执行以下命令完成 pip 升级、镜像源切换与依赖安装:

# 升级pip python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope==1.9.5 pip install transformers==4.35.2 pip install streamlit==1.24.0 pip install sentencepiece==0.1.99 pip install accelerate==0.24.1

各依赖包的作用与版本约束如下:

依赖包版本在本项目中的作用
modelscope1.9.5从魔搭(ModelScope)社区下载 InternLM-Chat-7B-V1.1 模型权重
transformers4.35.2加载与运行 CausalLM 模型,Lagent 的HFTransformerCasualLM后端依赖它
streamlit1.24.0提供 Web Demo 的前端交互框架(侧边栏、聊天消息、文件上传)
sentencepiece0.1.99InternLM 分词器依赖的 SentencePiece 库
accelerate0.24.1加速模型加载与推理的设备调度

模型下载:用 ModelScope 拉取 InternLM-Chat-7B-V1.1

/root/autodl-tmp路径下新建download.py文件,写入以下内容:

import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir = snapshot_download('Shanghai_AI_Laboratory/internlm-chat-7b-v1_1', cache_dir='/root/autodl-tmp', revision='master')

然后运行python /root/autodl-tmp/download.py执行下载。snapshot_download是 ModelScope 提供的快照下载接口,三个关键参数分别为:

  • 第一个参数:模型仓库 IDShanghai_AI_Laboratory/internlm-chat-7b-v1_1,即书生·浦语 7B 的 V1.1 版本;
  • cache_dir:模型下载保存路径,这里存到 AutoDL 的数据盘/root/autodl-tmp
  • revision:分支版本master

该模型大小为14 GB,下载大概需要10~20 分钟。下载完成后,模型文件会存放在/root/autodl-tmp/Shanghai_AI_Laboratory/internlm-chat-7b-v1_1目录下,这正是后续 Web Demo 代码中HFTransformerCasualLM加载模型时使用的路径。注意此下载方式与 01-InternLM-Chat-7B Transformers 部署调用.md 中下载internlm-chat-7b的方式完全一致,仅模型 ID 不同(V1.1 版本为internlm-chat-7b-v1_1)。

源码安装 Lagent:固定 Commit 保证可复现

Lagent 需要通过git clone拉取源码并以pip install -e .进行源码安装。在 AutoDL 上,先开启学术加速再执行安装,完成后关闭代理:

source /etc/network_turbo cd /root/autodl-tmp git clone https://github.com/InternLM/lagent.git git checkout 511b03889010c4811b1701abb153e02b8e94fb5e # 尽量保证和教程commit版本一致 cd lagent pip install -e . # 源码安装 unset http_proxy && unset https_proxy

这里有两个值得注意的细节:

  1. 固定 commitgit checkout 511b03889010c4811b1701abb153e02b8e94fb5e将仓库切换到与教程一致的版本。Lagent 迭代较快,接口(如ActionExecutorReActHFTransformerCasualLM的构造签名)可能随版本变化,锁定 commit 可最大程度保证下面的 Demo 代码开箱即用;
  2. pip install -e .(editable 模式):源码安装会将lagent包以软链接方式注册到当前 Python 环境,修改仓库内代码后无需重新安装即可生效,这也是后面"直接替换examples/react_web_demo.py文件内容"能立即生效的前提。

安装完成后,Lagent 的官方示例位于/root/autodl-tmp/lagent/examples/目录下,其中react_web_demo.py就是我们本次要改造的 Streamlit 前端入口。

重写 react_web_demo.py:智能体 Web 前端全解析

由于本次代码修改点较多,最稳妥的做法是直接将/root/autodl-tmp/lagent/examples/react_web_demo.py的内容整体替换为以下代码(与原教程保持一致):

import copy import os import streamlit as st from streamlit.logger import get_logger from lagent.actions import ActionExecutor, GoogleSearch, PythonInterpreter from lagent.agents.react import ReAct from lagent.llms import GPTAPI from lagent.llms.huggingface import HFTransformerCasualLM class SessionState: def init_state(self): """Initialize session state variables.""" st.session_state['assistant'] = [] st.session_state['user'] = [] #action_list = [PythonInterpreter(), GoogleSearch()] action_list = [PythonInterpreter()] st.session_state['plugin_map'] = { action.name: action for action in action_list } st.session_state['model_map'] = {} st.session_state['model_selected'] = None st.session_state['plugin_actions'] = set() def clear_state(self): """Clear the existing session state.""" st.session_state['assistant'] = [] st.session_state['user'] = [] st.session_state['model_selected'] = None if 'chatbot' in st.session_state: st.session_state['chatbot']._session_history = [] class StreamlitUI: def __init__(self, session_state: SessionState): self.init_streamlit() self.session_state = session_state def init_streamlit(self): """Initialize Streamlit's UI settings.""" st.set_page_config( layout='wide', page_title='lagent-web', page_icon='./docs/imgs/lagent_icon.png') # st.header(':robot_face: :blue[Lagent] Web Demo ', divider='rainbow') st.sidebar.title('模型控制') def setup_sidebar(self): """Setup the sidebar for model and plugin selection.""" model_name = st.sidebar.selectbox( '模型选择:', options=['gpt-3.5-turbo','internlm']) if model_name != st.session_state['model_selected']: model = self.init_model(model_name) self.session_state.clear_state() st.session_state['model_selected'] = model_name if 'chatbot' in st.session_state: del st.session_state['chatbot'] else: model = st.session_state['model_map'][model_name] plugin_name = st.sidebar.multiselect( '插件选择', options=list(st.session_state['plugin_map'].keys()), default=[list(st.session_state['plugin_map'].keys())[0]], ) plugin_action = [ st.session_state['plugin_map'][name] for name in plugin_name ] if 'chatbot' in st.session_state: st.session_state['chatbot']._action_executor = ActionExecutor( actions=plugin_action) if st.sidebar.button('清空对话', key='clear'): self.session_state.clear_state() uploaded_file = st.sidebar.file_uploader( '上传文件', type=['png', 'jpg', 'jpeg', 'mp4', 'mp3', 'wav']) return model_name, model, plugin_action, uploaded_file def init_model(self, option): """Initialize the model based on the selected option.""" if option not in st.session_state['model_map']: if option.startswith('gpt'): st.session_state['model_map'][option] = GPTAPI( model_type=option) else: st.session_state['model_map'][option] = HFTransformerCasualLM( '/root/autodl-tmp/Shanghai_AI_Laboratory/internlm-chat-7b-v1_1') return st.session_state['model_map'][option] def initialize_chatbot(self, model, plugin_action): """Initialize the chatbot with the given model and plugin actions.""" return ReAct( llm=model, action_executor=ActionExecutor(actions=plugin_action)) def render_user(self, prompt: str): with st.chat_message('user'): st.markdown(prompt) def render_assistant(self, agent_return): with st.chat_message('assistant'): for action in agent_return.actions: if (action): self.render_action(action) st.markdown(agent_return.response) def render_action(self, action): with st.expander(action.type, expanded=True): st.markdown( "<p style='text-align: left;display:flex;'> <span style='font-size:14px;font-weight:600;width:70px;text-align-last: justify;'>插 件</span><span style='width:14px;text-align:left;display:block;'>:</span><span style='flex:1;'>" # noqa E501 + action.type + '</span></p>', unsafe_allow_html=True) st.markdown( "<p style='text-align: left;display:flex;'> <span style='font-size:14px;font-weight:600;width:70px;text-align-last: justify;'>思考步骤</span><span style='width:14px;text-align:left;display:block;'>:</span><span style='flex:1;'>" # noqa E501 + action.thought + '</span></p>', unsafe_allow_html=True) if (isinstance(action.args, dict) and 'text' in action.args): st.markdown( "<p style='text-align: left;display:flex;'><span style='font-size:14px;font-weight:600;width:70px;text-align-last: justify;'> 执行内容</span><span style='width:14px;text-align:left;display:block;'>:</span></p>", # noqa E501 unsafe_allow_html=True) st.markdown(action.args['text']) self.render_action_results(action) def render_action_results(self, action): """Render the results of action, including text, images, videos, and audios.""" if (isinstance(action.result, dict)): st.markdown( "<p style='text-align: left;display:flex;'><span style='font-size:14px;font-weight:600;width:70px;text-align-last: justify;'> 执行结果</span><span style='width:14px;text-align:left;display:block;'>:</span></p>", # noqa E501 unsafe_allow_html=True) if 'text' in action.result: st.markdown( "<p style='text-align: left;'>" + action.result['text'] + '</p>', unsafe_allow_html=True) if 'image' in action.result: image_path = action.result['image'] image_data = open(image_path, 'rb').read() st.image(image_data, caption='Generated Image') if 'video' in action.result: video_data = action.result['video'] video_data = open(video_data, 'rb').read() st.video(video_data) if 'audio' in action.result: audio_data = action.result['audio'] audio_data = open(audio_data, 'rb').read() st.audio(audio_data) def main(): logger = get_logger(__name__) # Initialize Streamlit UI and setup sidebar if 'ui' not in st.session_state: session_state = SessionState() session_state.init_state() st.session_state['ui'] = StreamlitUI(session_state) else: st.set_page_config( layout='wide', page_title='lagent-web', page_icon='./docs/imgs/lagent_icon.png') # st.header(':robot_face: :blue[Lagent] Web Demo ', divider='rainbow') model_name, model, plugin_action, uploaded_file = st.session_state[ 'ui'].setup_sidebar() # Initialize chatbot if it is not already initialized # or if the model has changed if 'chatbot' not in st.session_state or model != st.session_state[ 'chatbot']._llm: st.session_state['chatbot'] = st.session_state[ 'ui'].initialize_chatbot(model, plugin_action) for prompt, agent_return in zip(st.session_state['user'], st.session_state['assistant']): st.session_state['ui'].render_user(prompt) st.session_state['ui'].render_assistant(agent_return) # User input form at the bottom (this part will be at the bottom) # with st.form(key='my_form', clear_on_submit=True): if user_input := st.chat_input(''): st.session_state['ui'].render_user(user_input) st.session_state['user'].append(user_input) # Add file uploader to sidebar if uploaded_file: file_bytes = uploaded_file.read() file_type = uploaded_file.type if 'image' in file_type: st.image(file_bytes, caption='Uploaded Image') elif 'video' in file_type: st.video(file_bytes, caption='Uploaded Video') elif 'audio' in file_type: st.audio(file_bytes, caption='Uploaded Audio') # Save the file to a temporary location and get the path file_path = os.path.join(root_dir, uploaded_file.name) with open(file_path, 'wb') as tmpfile: tmpfile.write(file_bytes) st.write(f'File saved at: {file_path}') user_input = '我上传了一个图像,路径为: {file_path}. {user_input}'.format( file_path=file_path, user_input=user_input) agent_return = st.session_state['chatbot'].chat(user_input) st.session_state['assistant'].append(copy.deepcopy(agent_return)) logger.info(agent_return.inner_steps) st.session_state['ui'].render_assistant(agent_return) if __name__ == '__main__': root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) root_dir = os.path.join(root_dir, 'tmp_dir') os.makedirs(root_dir, exist_ok=True) main()

代码结构拆解:智能体的"大脑"与"手脚"

从代码结构看,这个 Demo 由三部分组成,对应了 Lagent 智能体的核心抽象:

1. 模型后端(init_model方法)

侧边栏模型选择提供gpt-3.5-turbointernlm两个选项:

  • 选择gpt-3.5-turbo时,创建GPTAPI(model_type=option),即调用 OpenAI 兼容 API;
  • 选择internlm时,创建HFTransformerCasualLM('/root/autodl-tmp/Shanghai_AI_Laboratory/internlm-chat-7b-v1_1'),即直接加载我们上一步下载到本地的 V1.1 模型权重。

HFTransformerCasualLM来自lagent.llms.huggingface,从命名与用法看,它封装了 HuggingFace Transformers 的 CausalLM 推理逻辑,是 Lagent 将"任意本地开源模型"接入智能体框架的标准入口。模型实例缓存在st.session_state['model_map']中,切换模型时通过clear_state()清空历史,避免重复加载。

2. 插件系统(init_statesetup_sidebar方法)

SessionState.init_state中默认启用的插件列表为:

#action_list = [PythonInterpreter(), GoogleSearch()] action_list = [PythonInterpreter()]
  • PythonInterpreter():Python 代码解释器插件,负责执行模型生成的代码并返回执行结果,是本 Demo 的核心工具;
  • GoogleSearch()被注释掉:从代码看该插件用于联网搜索,之所以默认不启用,可以推断是因为其依赖 Google 搜索 API 凭证,本地环境无法直接开箱使用。

插件通过ActionExecutor(actions=plugin_action)统一调度,侧边栏的插件选择多选框可在运行时动态增减插件集合。

3. ReAct Agent(initialize_chatbot方法)

return ReAct( llm=model, action_executor=ActionExecutor(actions=plugin_action))

ReActlagent.agents.react中定义的智能体主体,其构造参数只有两个:推理模型llm与动作执行器action_executor。从调用链看,用户输入经chatbot.chat(user_input)进入 ReAct 循环:模型产出"思考步骤 + 动作调用"(存于agent_return.actions),ActionExecutor执行对应插件(如把生成的 Python 代码送入解释器),最后把动作结果回传给模型组织最终回复(存于agent_return.response)。render_action将每个动作的插件名、思考步骤、执行内容、执行结果分开展示在可展开面板中,这正是我们在运行截图中看到的"模型写代码 → 执行 → 出结果"的可视化依据。

4. 多模态结果渲染与文件上传

render_action_results支持渲染textimagevideoaudio四类动作结果,说明 Lagent 的 Action 结果协议本身是多模态的。侧边栏的上传文件组件支持png/jpg/jpeg/mp4/mp3/wav,上传的文件会保存到脚本自动创建的上传目录,并把文件路径拼接进用户输入(我上传了一个图像,路径为: ...),供模型在后续推理中引用。

Demo 运行:启动服务、映射端口、验证数学求解

环境与代码就绪后,执行以下命令启动 Streamlit 服务:

streamlit run /root/autodl-tmp/lagent/examples/react_web_demo.py --server.address 127.0.0.1 --server.port 6006

其中--server.address 127.0.0.1 --server.port 6006将服务绑定到本机 6006 端口。由于服务运行在 AutoDL 云服务器上,还需要"用同样的方法将端口映射到本地"——即在 AutoDL 控制台为该实例开放 6006 端口并做本地转发,具体操作流程可参考仓库中的 02-AutoDL开放端口.md,本地浏览器即可通过映射后的地址访问 Web 页面。

运行成功后,在 Web 页面左侧选择InternLM模型,等待模型加载完毕(首次加载需将 14GB 权重读入显存,耗时较长属正常现象),然后输入数学问题:已知2x+3=10,求x

此时完整链路为:InternLM-Chat-7B-V1.1理解题意并生成解此题的 Python 代码 →Lagent调度代码解释器插件执行该代码 → 返回精确结果x=3.5,而不是模型凭空"估算"一个数字。以下为实际运行效果截图:

小结:从"会聊天"到"会干活"的关键一步

通过本文的完整流程,我们完成了:

  1. 环境与模型:复用 InternLM-Chat-7B 教程的 AutoDL 环境,用 ModelScope 下载 14GB 的 InternLM-Chat-7B-V1.1 权重;
  2. 框架安装:以固定 commit 源码安装 Lagent,保证接口与教程一致;
  3. 前端改造:用一套同时支持GPTAPI与本地HFTransformerCasualLM双后端、可动态增删插件、支持多模态结果渲染的 Streamlit Demo 替换官方示例;
  4. 效果验证:通过"解方程"实例验证了 ReAct 智能体"模型生成代码 + 解释器执行"的闭环。

从源码结构可以推断,这套 Web Demo 的本质是 Lagent 框架的薄封装:真正决定智能体能力上限的是ReAct的推理循环与ActionExecutor管理的插件集合。掌握了本教程的改造方法后,你可以将插件列表扩展为更多工具(如代码中的GoogleSearch),或把HFTransformerCasualLM的模型路径替换为仓库内其他教程部署的开源模型,将任意模型快速升级为具备工具调用能力的智能体。

此外,若想进一步了解 InternLM-Chat-7B-V1.1 的更多玩法,可继续阅读仓库中的 06-InternLM接入LangChain搭建知识库助手.md(RAG 知识库助手)与 05-浦语灵笔图文理解&创作.md(多模态图文创作)。

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询