书生·浦语大模型实战营之Lagent AgentLego 智能体应用搭建

news2024/12/22 9:12:33

书生·浦语大模型实战营之Lagent & AgentLego 智能体应用搭建
在这里插入图片描述

Lagent 简介

Lagent 是一个轻量级开源智能体框架,旨在让用户可以高效地构建基于大语言模型的智能体。同时它也提供了一些典型工具以增强大语言模型的能力。

Lagent 目前已经支持了包括 AutoGPT、ReAct 等在内的多个经典智能体范式,也支持了如下工具:

  • Arxiv 搜索
  • Bing 地图
  • Google 学术搜索
  • Google 搜索
  • 交互式 IPython 解释器
  • IPython 解释器
  • PPT
  • Python 解释器

AgentLego 简介

AgentLego 是一个提供了多种开源工具 API 的多模态工具包,旨在像是乐高积木一样,让用户可以快速简便地拓展自定义工具,从而组装出自己的智能体。通过 AgentLego 算法库,不仅可以直接使用多种工具,也可以利用这些工具,在相关智能体框架(如 Lagent,Transformers Agent 等)的帮助下,快速构建可以增强大语言模型能力的智能体。

AgentLego 目前提供了如下工具:
在这里插入图片描述
Lagent 是一个智能体框架,而 AgentLego 与大模型智能体并不直接相关,而是作为工具包,在相关智能体的功能支持模块发挥作用。

两者之间的关系可以用下图来表示:
在这里插入图片描述

环境配置

在创建开发机界面选择镜像为 Cuda12.2-conda,并选择 GPU 为30% A100
在这里插入图片描述

创建一个用于存放 Agent 相关文件的目录

mkdir -p /root/agent

配置 conda 环境,可以输入如下指令

studio-conda -t agent -o pytorch-2.1.2

在这里插入图片描述

安装 Lagent 和 AgentLego

Lagent 和 AgentLego 都提供了两种安装方法,一种是通过 pip 直接进行安装,另一种则是从源码进行安装。为了方便使用 Lagent 的 Web Demo 以及 AgentLego 的 WebUI,我们选择直接从源码进行安装。 此处附上源码安装的相关帮助文档:

Lagent:https://lagent.readthedocs.io/zh-cn/latest/get_started/install.html
AgentLego:https://agentlego.readthedocs.io/zh-cn/latest/get_started.html

可以执行如下命令进行安装:

cd /root/agent
conda activate agent
git clone https://gitee.com/internlm/lagent.git
cd lagent && git checkout 581d9fb && pip install -e . && cd ..
git clone https://gitee.com/internlm/agentlego.git
cd agentlego && git checkout 7769e0d && pip install -e . && cd ..

在这里插入图片描述

安装其他依赖

安装其他将要用到的依赖库,如 LMDeploy,可以执行如下命令:

conda activate agent
pip install lmdeploy==0.3.0

在这里插入图片描述
git clone 的方法 下载 tutorial

cd /root/agent
git clone -b camp2 https://gitee.com/internlm/Tutorial.git

在这里插入图片描述

Lagent:轻量级智能体框架

在这一部分中,我们将带大家体验 Lagent 的 Web Demo,使用 Lagent 自定义工具,并体验自定义工具的效果。

详细文档可以访问:Lagent:轻量级智能体框架。

Lagent Web Demo

使用 LMDeploy 部署
由于 Lagent 的 Web Demo 需要用到 LMDeploy 所启动的 api_server,因此我们首先按照下图指示在 vscode terminal 中执行如下代码使用 LMDeploy 启动一个 api_server

conda activate agent
lmdeploy serve api_server /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-7b \
                            --server-name 127.0.0.1 \
                            --model-name internlm2-chat-7b \
                            --cache-max-entry-count 0.1

启动并使用 Lagent Web Demo
接下来我们按照下图指示新建一个 terminal 以启动 Lagent Web Demo。在新建的 terminal 中执行如下指令

conda activate agent
cd /root/agent/lagent/examples
streamlit run internlm2_agent_web_demo.py --server.address 127.0.0.1 --server.port 7860

在这里插入图片描述

在这里插入图片描述

等待 LMDeploy 的 api_server 与 Lagent Web Demo 完全启动后,在本地进行端口映射,将 LMDeploy api_server 的23333端口以及 Lagent Web Demo 的7860端口映射到本地。可以执行:

ssh -CNg -L 7860:127.0.0.1:7860 -L 23333:127.0.0.1:23333 root@ssh.intern-ai.org.cn -p   43844

在这里插入图片描述

在本地的浏览器页面中打开 http://localhost:7860 以使用 Lagent Web Demo。首先输入模型 IP 为 127.0.0.1:23333,在输入完成后按下回车键以确认。并选择插件为 ArxivSearch,以让模型获得在 arxiv 上搜索论文的能力。

系统提示词:当开启工具以及代码时,根据需求选择合适的工具进行调用

数据分析提示词:你现在已经能够在一个有状态的 Jupyter 笔记本环境中运行 Python 代码。当你向 python 发送含有 Python 代码的消息时,它将在该环境中执行。这个工具适用于多种场景,如数据分析或处理(包括数据操作、统计分析、图表绘制),复杂的计算问题(解决数学和物理难题),编程示例(理解编程概念或特性),文本处理和分析(比如文本解析和自然语言处理),机器学习和数据科学(用于展示模型训练和数据可视化),以及文件操作和数据导入(处理CSV、JSON等格式的文件)。

插件提示词:
你可以使用如下工具:
{prompt}
如果你已经获得足够信息,请直接给出答案. 避免不必要的工具调用! 同时注意你可以使用的工具,不要随意捏造!

输入“请帮我搜索 InternLM2 Technical Report” 以让模型搜索书生·浦语2的技术报告。效果如下图所示,可以看到模型正确输出了 InternLM2 技术报告的相关信息。尽管还输出了其他论文,但这是由 arxiv 搜索 API 的相关行为导致的
v
lagent/agents/internlm2_agent.py

import json
import logging
from copy import deepcopy
from typing import Dict, List, Optional, Union

from lagent.actions import ActionExecutor
from lagent.agents.base_agent import BaseAgent
from lagent.llms import BaseAPIModel, BaseModel
from lagent.schema import ActionReturn, ActionStatusCode, AgentReturn, AgentStatusCode, ModelStatusCode  # noqa: E501

API_PREFIX = (
    "This is the subfunction for tool '{tool_name}', you can use this tool. "
    'The description of this function is: \n{description}')

META_CN = ('当开启工具以及代码时,根据需求选择合适的工具进行调用')

INTERPRETER_CN = ('你现在已经能够在一个有状态的 Jupyter 笔记本环境中运行 Python 代码。'
                  '当你向 python 发送含有 Python 代码的消息时,它将在该环境中执行。'
                  '这个工具适用于多种场景,如数据分析或处理(包括数据操作、统计分析、图表绘制),'
                  '复杂的计算问题(解决数学和物理难题),编程示例(理解编程概念或特性),'
                  '文本处理和分析(比如文本解析和自然语言处理),'
                  '机器学习和数据科学(用于展示模型训练和数据可视化),'
                  '以及文件操作和数据导入(处理CSV、JSON等格式的文件)。')

PLUGIN_CN = ('你可以使用如下工具:'
             '\n{prompt}\n'
             '如果你已经获得足够信息,请直接给出答案. 避免不必要的工具调用! '
             '同时注意你可以使用的工具,不要随意捏造!')


class Internlm2Protocol:

    def __init__(
        self,
        meta_prompt: str = META_CN,
        interpreter_prompt: str = INTERPRETER_CN,
        plugin_prompt: str = PLUGIN_CN,
        few_shot: Optional[List] = None,
        language: Dict = dict(
            begin='',
            end='',
            belong='assistant',
        ),
        tool: Dict = dict(
            begin='{start_token}{name}\n',
            start_token='<|action_start|>',
            name_map=dict(plugin='<|plugin|>', interpreter='<|interpreter|>'),
            belong='assistant',
            end='<|action_end|>\n',
        ),
        execute: Dict = dict(
            role='execute', begin='', end='', fallback_role='environment'),
    ) -> None:
        self.meta_prompt = meta_prompt
        self.interpreter_prompt = interpreter_prompt
        self.plugin_prompt = plugin_prompt
        self.roles_cfg = dict(tool=tool, language=language)
        self.language = language
        self.execute = execute
        self.tool = tool
        self.few_shot = few_shot

    def format_sub_role(self, messages: List[Dict]) -> List[Dict]:

        def format_interpreter(message):
            if isinstance(message['content'], dict):
                # assert message['content']['name'] == 'IPythonInterpreter'
                return dict(
                    role=message['role'],
                    name=message['name'],
                    content=message['content']['parameters']['command'])
            else:
                return message

        def format_plugin(message):
            if isinstance(message['content'], dict):
                return dict(
                    role=message['role'],
                    name=message['name'],
                    content=json.dumps(message['content']))
            else:
                return message

        new_message = list()
        for message in messages:
            if message['role'] in [
                    'assistant', 'user', 'system', 'environment'
            ]:
                new_message.append(message)
                continue
            role_cfg = self.roles_cfg[message['role']]
            begin = role_cfg['begin']
            if message['role'] == 'tool':
                if message['name'] == 'interpreter':
                    message = format_interpreter(message)
                elif message['name'] == 'plugin':
                    message = format_plugin(message)
                else:
                    raise NotImplementedError
                begin = role_cfg['begin'].format(
                    start_token=role_cfg.get('start_token', ''),
                    name=role_cfg.get('name_map', {}).get(message['name'], ''))
            new_content = begin + message['content'] + role_cfg['end']
            if role_cfg.get('fallback_role'):
                new_message.append(
                    dict(role=role_cfg['fallback_role'], content=new_content))
            elif role_cfg.get('belong'):
                if new_message[-1]['role'] != role_cfg.get('belong'):
                    new_message.append(
                        dict(role=role_cfg.get('belong'), content=new_content))
                else:
                    new_message[-1]['content'] += new_content
            else:
                new_message.append(
                    dict(role=message['role'], content=new_content))

        return new_message

    def format(self,
               inner_step: List[Dict],
               plugin_executor: ActionExecutor = None,
               interpreter_executor: ActionExecutor = None,
               **kwargs) -> list:
        formatted = []
        if self.meta_prompt:
            formatted.append(dict(role='system', content=self.meta_prompt))
        if interpreter_executor and self.interpreter_prompt:
            interpreter_info = interpreter_executor.get_actions_info()[0]
            interpreter_prompt = self.interpreter_prompt.format(
                code_prompt=interpreter_info['description'])
            formatted.append(
                dict(
                    role='system',
                    content=interpreter_prompt,
                    name='interpreter'))
        if plugin_executor and plugin_executor.actions and self.plugin_prompt:
            plugin_descriptions = []
            for api_info in plugin_executor.get_actions_info():
                plugin = deepcopy(api_info)
                if isinstance(api_info, dict):
                    tool_name = api_info['name'].split('.')[0]
                    plugin['description'] = API_PREFIX.format(
                        tool_name=tool_name, description=plugin['description'])
                    # only keep required parameters
                    required_parameters = [
                        param for param in plugin['parameters']
                        if param['name'] in plugin['required']
                    ]
                    plugin['parameters'] = required_parameters
                plugin_descriptions.append(plugin)
            plugin_prompt = self.plugin_prompt.format(
                prompt=json.dumps(
                    plugin_descriptions, ensure_ascii=False, indent=4))
            formatted.append(
                dict(role='system', content=plugin_prompt, name='plugin'))
        if self.few_shot:
            for few_shot in self.few_shot:
                formatted += self.format_sub_role(few_shot)
        formatted += self.format_sub_role(inner_step)
        return formatted

    def parse(self, message, plugin_executor: ActionExecutor,
              interpreter_executor: ActionExecutor):
        if self.language['begin']:
            message = message.split(self.language['begin'])[-1]
        if self.tool['name_map']['plugin'] in message:
            message, action = message.split(
                f"{self.tool['start_token']}{self.tool['name_map']['plugin']}")
            action = action.split(self.tool['end'].strip())[0]
            return 'plugin', message, action
        if self.tool['name_map']['interpreter'] in message:
            message, code = message.split(
                f"{self.tool['start_token']}"
                f"{self.tool['name_map']['interpreter']}")
            code = code.split(self.tool['end'].strip())[0].strip()
            return 'interpreter', message, dict(
                name=interpreter_executor.action_names()[0],
                parameters=dict(
                    command=code)) if interpreter_executor else None
        return None, message.split(self.tool['start_token'])[0], None

    def format_response(self, action_return, name) -> dict:
        if action_return.state == ActionStatusCode.SUCCESS:
            response = action_return.format_result()
        else:
            response = str(action_return.errmsg)
        content = self.execute['begin'] + response + self.execute['end']
        if self.execute.get('fallback_role'):
            return dict(
                role=self.execute['fallback_role'], content=content, name=name)
        elif self.execute.get('belong'):
            return dict(
                role=self.execute['belong'], content=content, name=name)
        return dict(role=self.execute['role'], content=response, name=name)


class Internlm2Agent(BaseAgent):

    def __init__(self,
                 llm: Union[BaseModel, BaseAPIModel],
                 plugin_executor: ActionExecutor = None,
                 interpreter_executor: ActionExecutor = None,
                 protocol=Internlm2Protocol(),
                 max_turn: int = 3) -> None:
        self.max_turn = max_turn
        self._interpreter_executor = interpreter_executor
        super().__init__(
            llm=llm, action_executor=plugin_executor, protocol=protocol)

    def chat(self, message: Union[str, Dict], **kwargs) -> AgentReturn:
        if isinstance(message, str):
            message = dict(role='user', content=message)
        if isinstance(message, dict):
            message = [message]
        inner_history = message[:]
        offset = len(inner_history)
        agent_return = AgentReturn()
        for _ in range(self.max_turn):
            # list of dict
            prompt = self._protocol.format(
                inner_step=inner_history,
                plugin_executor=self._action_executor,
                interpreter_executor=self._interpreter_executor,
            )
            response = self._llm.chat(prompt, **kwargs)
            name, language, action = self._protocol.parse(
                message=response,
                plugin_executor=self._action_executor,
                interpreter_executor=self._interpreter_executor,
            )
            if name:
                if name == 'plugin':
                    if self._action_executor:
                        executor = self._action_executor
                    else:
                        logging.info(msg='No plugin is instantiated!')
                        continue
                    try:
                        action = json.loads(action)
                    except Exception as e:
                        logging.info(msg=f'Invaild action {e}')
                        continue
                elif name == 'interpreter':
                    if self._interpreter_executor:
                        executor = self._interpreter_executor
                    else:
                        logging.info(msg='No interpreter is instantiated!')
                        continue
                else:
                    logging.info(
                        msg=(f"Invalid name '{name}'. Currently only 'plugin' "
                             "and 'interpreter' are supported."))
                    continue
                action_return: ActionReturn = executor(action['name'],
                                                       action['parameters'])
                action_return.thought = language
                agent_return.actions.append(action_return)
            inner_history.append(dict(role='language', content=language))
            if not name or action_return.type == executor.finish_action.name:
                agent_return.response = language
                agent_return.state = AgentStatusCode.END
                break
            else:
                inner_history.append(
                    dict(role='tool', content=action, name=name))
                inner_history.append(
                    self._protocol.format_response(action_return, name=name))
        agent_return.inner_steps = inner_history[offset:]
        return agent_return

    def stream_chat(self, message: List[dict], **kwargs) -> AgentReturn:
        if isinstance(message, str):
            message = dict(role='user', content=message)
        if isinstance(message, dict):
            message = [message]
        inner_history = message[:]
        offset = len(inner_history)
        agent_return = AgentReturn()
        last_agent_state = AgentStatusCode.SESSION_READY
        for _ in range(self.max_turn):
            # list of dict
            prompt = self._protocol.format(
                inner_step=inner_history,
                plugin_executor=self._action_executor,
                interpreter_executor=self._interpreter_executor,
            )
            response = ''
            for model_state, res, _ in self._llm.stream_chat(prompt, **kwargs):
                model_state: ModelStatusCode
                response = res
                if model_state.value < 0:
                    agent_return.state = getattr(AgentStatusCode,
                                                 model_state.name)
                    yield deepcopy(agent_return)
                    return
                else:
                    name, language, action = self._protocol.parse(
                        message=response,
                        plugin_executor=self._action_executor,
                        interpreter_executor=self._interpreter_executor,
                    )
                    if name:
                        if model_state == ModelStatusCode.END:
                            agent_state = last_agent_state + 1
                            if name == 'plugin':
                                if self._action_executor:
                                    executor = self._action_executor
                                else:
                                    logging.info(
                                        msg='No plugin is instantiated!')
                                    continue
                                try:
                                    action = json.loads(action)
                                except Exception as e:
                                    logging.info(msg=f'Invaild action {e}')
                                    continue
                            elif name == 'interpreter':
                                if self._interpreter_executor:
                                    executor = self._interpreter_executor
                                else:
                                    logging.info(
                                        msg='No interpreter is instantiated!')
                                    continue
                            agent_return.state = agent_state
                            agent_return.response = action
                        else:
                            agent_state = (
                                AgentStatusCode.PLUGIN_START if name
                                == 'plugin' else AgentStatusCode.CODING)
                            if agent_state != last_agent_state:
                                # agent_return.state = agent_state
                                agent_return.response = language
                                yield deepcopy(agent_return)
                            agent_return.state = agent_state
                            agent_return.response = action
                    else:
                        agent_state = AgentStatusCode.STREAM_ING
                        agent_return.state = agent_state
                        agent_return.response = language
                    last_agent_state = agent_state
                    yield deepcopy(agent_return)
            if name:
                action_return: ActionReturn = executor(action['name'],
                                                       action['parameters'])
                action_return.thought = language
                agent_return.actions.append(action_return)
            inner_history.append(dict(role='language', content=language))
            if not name:
                agent_return.response = language
                break
            elif action_return.type == executor.finish_action.name:
                try:
                    response = action_return.args['text']['response']
                except Exception:
                    logging.info(msg='Unable to parse FinishAction.')
                    response = ''
                agent_return.response = response
                break
            else:
                inner_history.append(
                    dict(role='tool', content=action, name=name))
                inner_history.append(
                    self._protocol.format_response(action_return, name=name))
                agent_state += 1
                agent_return.state = agent_state
                yield agent_return
        agent_return.inner_steps = deepcopy(inner_history[offset:])
        agent_return.state = AgentStatusCode.END
        yield agent_return

lagent/actions/arxiv_search.py 代码

from typing import Optional, Type

from lagent.actions.base_action import BaseAction, tool_api
from lagent.actions.parser import BaseParser, JsonParser
from lagent.schema import ActionReturn, ActionStatusCode


class ArxivSearch(BaseAction):
    """Search information from Arxiv.org. \
Useful for when you need to answer questions about Physics, Mathematics, \
Computer Science, Quantitative Biology, Quantitative Finance, Statistics, \
Electrical Engineering, and Economics from scientific articles on arxiv.org.
    """

    def __init__(self,
                 top_k_results: int = 3,
                 max_query_len: int = 300,
                 doc_content_chars_max: int = 1500,
                 description: Optional[dict] = None,
                 parser: Type[BaseParser] = JsonParser,
                 enable: bool = True):
        super().__init__(description, parser, enable)
        self.top_k_results = top_k_results
        self.max_query_len = max_query_len
        self.doc_content_chars_max = doc_content_chars_max

    @tool_api(explode_return=True)
    def get_arxiv_article_information(self, query: str) -> dict:
        """Run Arxiv search and get the article meta information.

        Args:
            query (:class:`str`): the content of search query

        Returns:
            :class:`dict`: article information
                * content (str): a list of 3 arxiv search papers
        """
        import arxiv

        try:
            results = arxiv.Search(  # type: ignore
                query[:self.max_query_len],
                max_results=self.top_k_results).results()
        except Exception as exc:
            return ActionReturn(
                errmsg=f'Arxiv exception: {exc}',
                state=ActionStatusCode.HTTP_ERROR)
        docs = [
            f'Published: {result.updated.date()}\nTitle: {result.title}\n'
            f'Authors: {", ".join(a.name for a in result.authors)}\n'
            f'Summary: {result.summary[:self.doc_content_chars_max]}'
            for result in results
        ]
        if docs:
            return {'content': '\n\n'.join(docs)}
        return {'content': 'No good Arxiv Result was found'}

用 Lagent 自定义工具

在本节中,我们将基于 Lagent 自定义一个工具。Lagent 中关于工具部分的介绍文档位于 https://lagent.readthedocs.io/zh-cn/latest/tutorials/action.html 。使用 Lagent 自定义工具主要分为以下几步:

  • 继承 BaseAction 类
  • 实现简单工具的 run 方法;或者实现工具包内每个子工具的功能
  • 简单工具的 run 方法可选被 tool_api 装饰;工具包内每个子工具的功能都需要被 tool_api 装饰

下面我们将实现一个调用和风天气 API 的工具以完成实时天气查询的功能。

创建工具文件

首先通过 touch /root/agent/lagent/lagent/actions/weather.py 新建工具文件,该文件内容如下

vim /root/agent/lagent/lagent/actions/weather.py

import json
import os
import requests
from typing import Optional, Type

from lagent.actions.base_action import BaseAction, tool_api
from lagent.actions.parser import BaseParser, JsonParser
from lagent.schema import ActionReturn, ActionStatusCode

class WeatherQuery(BaseAction):
    """Weather plugin for querying weather information."""
    
    def __init__(self,
                 key: Optional[str] = None,
                 description: Optional[dict] = None,
                 parser: Type[BaseParser] = JsonParser,
                 enable: bool = True) -> None:
        super().__init__(description, parser, enable)
        key = os.environ.get('WEATHER_API_KEY', key)
        if key is None:
            raise ValueError(
                'Please set Weather API key either in the environment '
                'as WEATHER_API_KEY or pass it as `key`')
        self.key = key
        self.location_query_url = 'https://geoapi.qweather.com/v2/city/lookup'
        self.weather_query_url = 'https://devapi.qweather.com/v7/weather/now'

    @tool_api
    def run(self, query: str) -> ActionReturn:
        """一个天气查询API。可以根据城市名查询天气信息。
        
        Args:
            query (:class:`str`): The city name to query.
        """
        tool_return = ActionReturn(type=self.name)
        status_code, response = self._search(query)
        if status_code == -1:
            tool_return.errmsg = response
            tool_return.state = ActionStatusCode.HTTP_ERROR
        elif status_code == 200:
            parsed_res = self._parse_results(response)
            tool_return.result = [dict(type='text', content=str(parsed_res))]
            tool_return.state = ActionStatusCode.SUCCESS
        else:
            tool_return.errmsg = str(status_code)
            tool_return.state = ActionStatusCode.API_ERROR
        return tool_return
    
    def _parse_results(self, results: dict) -> str:
        """Parse the weather results from QWeather API.
        
        Args:
            results (dict): The weather content from QWeather API
                in json format.
        
        Returns:
            str: The parsed weather results.
        """
        now = results['now']
        data = [
            f'数据观测时间: {now["obsTime"]}',
            f'温度: {now["temp"]}°C',
            f'体感温度: {now["feelsLike"]}°C',
            f'天气: {now["text"]}',
            f'风向: {now["windDir"]},角度为 {now["wind360"]}°',
            f'风力等级: {now["windScale"]},风速为 {now["windSpeed"]} km/h',
            f'相对湿度: {now["humidity"]}',
            f'当前小时累计降水量: {now["precip"]} mm',
            f'大气压强: {now["pressure"]} 百帕',
            f'能见度: {now["vis"]} km',
        ]
        return '\n'.join(data)

    def _search(self, query: str):
        # get city_code
        try:
            city_code_response = requests.get(
                self.location_query_url,
                params={'key': self.key, 'location': query}
            )
        except Exception as e:
            return -1, str(e)
        if city_code_response.status_code != 200:
            return city_code_response.status_code, city_code_response.json()
        city_code_response = city_code_response.json()
        if len(city_code_response['location']) == 0:
            return -1, '未查询到城市'
        city_code = city_code_response['location'][0]['id']
        # get weather
        try:
            weather_response = requests.get(
                self.weather_query_url,
                params={'key': self.key, 'location': city_code}
            )
        except Exception as e:
            return -1, str(e)
        return weather_response.status_code, weather_response.json()

为了获得稳定的天气查询服务, 首先要获取 API KEY。打开 https://dev.qweather.com/docs/api/

在这里插入图片描述

体验自定义工具效果

在两个 terminal 中分别启动 LMDeploy 服务和 Tutorial 已经写好的用于这部分的 Web Demo

conda activate agent
lmdeploy serve api_server /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-7b \
                            --server-name 127.0.0.1 \
                            --model-name internlm2-chat-7b \
                            --cache-max-entry-count 0.1
export WEATHER_API_KEY=2.2节获取的API KEY
# 比如 export WEATHER_API_KEY=1234567890abcdef
conda activate agent
cd /root/agent/Tutorial/agent
streamlit run internlm2_weather_web_demo.py --server.address 127.0.0.1 --server.port 7860

在本地执行如下操作以进行端口映射

在这里插入图片描述
在输入模型地址并选择好工具后,就可以开始体验了。

在这里插入图片描述
读者可以关注大模型返回的工具名称及参数。query参数解析为上海

{
    "name": "WeatherQuery",
    "parameters": {
        "query": "上海"
    }
}

AgentLego:组装智能体“乐高”

使用 AgentLego 工具,体验 AgentLego 的 WebUI,以及基于 AgentLego 自定义工具并体验自定义工具的效果。

https://github.com/InternLM/Tutorial/tree/camp2/agent

https://github.com/InternLM/Tutorial/blob/camp2/agent/lagent.md

https://github.com/InternLM/Tutorial/blob/camp2/agent/agentlego.md

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1602592.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【系统分析师】应用数学部分

文章目录 1、图论应用1.1 最小生成树1.2 最短路径1.3 网络与最大流量 2、运筹方法2.1 关键路径法2.2 线性规划2.3 动态规划2.4 预测与决策2.4.1 囚徒困境2.4.2 实例&#xff1a;商业竞争 2.5 状态转移矩阵2.6 排队论2.7 决策2.7.1 决策2.7.2不确定型决策2.7.3 决策树2.7.4 决策…

4.17号驱动

中断子系统 1. 中断工作原理 1.1 异常处理流程 保存现场(cpu自动完成) 保存cpsr寄存器中的值&#xff0c;到spsr_寄存器中 修改cpsr寄存器中的值 修改状态位(T位) 根据需要禁止相应的中断位(I/F) 修改对应模式位 保存函数的返回地址到lr寄存器中 修改pc指向异常向量表 …

Realsense D455 调试

1 Realsense D455 配置&#xff1a; RGB&#xff1a;彩色相机&#xff0c;FOV&#xff08;h&#xff0c;v&#xff09;&#xff08; 90*65 &#xff09;红外点阵发射&#xff1a;位于上图中RGB右边&#xff0c;发射特定模式的红外光&#xff0c;通常是一种点阵图案&#xff0c…

深度学习架构(CNN、RNN、GAN、Transformers、编码器-解码器架构)的友好介绍。

一、说明 本博客旨在对涉及卷积神经网络 &#xff08;CNN&#xff09;、递归神经网络 &#xff08;RNN&#xff09;、生成对抗网络 &#xff08;GAN&#xff09;、转换器和编码器-解码器架构的深度学习架构进行友好介绍。让我们开始吧&#xff01;&#xff01; 二、卷积神经网络…

Dryad Girl Fawnia

一个可爱的Dryad Girl Fawnia的三维模型。她有ARKit混合形状,人形装备,多种颜色可供选择。她将是一个完美的角色,幻想或装扮游戏。 🔥 Dryad Girl | Fawnia 一个可爱的Dryad Girl Fawnia的三维模型。她有ARKit混合形状,人形装备,多种颜色可供选择。她将是一个完美的角色…

网络攻防演练:一场针锋相对的技术博弈与安全防护实践

随着ChatGPT5的即将上线&#xff0c;其安全防护能力面临更为严峻的考验。网络攻防演练作为检验系统安全性能、提升防御体系的关键环节&#xff0c;对于确保ChatGPT5的安全稳定运行具有重要意义。本文将深入探讨网络攻击与防守之间的动态关系&#xff0c;并提供在网络攻防演练中…

【Leetcode每日一题】 分治 - 颜色分类(难度⭐⭐)(57)

1. 题目解析 题目链接&#xff1a;75. 颜色分类 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路解析 本算法采用三指针法&#xff0c;将数组划分为三个区域&#xff0c;分别用于存放值为0、1和2的元素。通过…

vivado 设置 VIO 核以执行测量、查看 VIO 核状态

设置 VIO 核以执行测量 您添加到自己的设计中的 VIO 核会显示在“硬件 (Hardware) ”窗口中的目标器件下。如果未显示这些 VIO 核 &#xff0c; 请右键 单击器件并选择“ Refresh Hardware ”。这样将重新扫描 FPGA 或 ACAP 并刷新“ Hardware ”窗口。 注释 &#xff…

【免费】基于SOE算法的多时段随机配电网重构方法

1 主要内容 该程序是完全复现《Switch Opening and Exchange Method for Stochastic Distribution Network Reconfiguration》&#xff0c;也是一个开源代码&#xff0c;网上有些人卖的还挺贵&#xff0c;本次免费分享给大家&#xff0c;代码主要做的是一个通过配电网重构获取…

“面包板”是什么?有啥用?

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

一种范围可调式测径仪 满足生产各规格检测!

摘要&#xff1a;范围可调式测径仪&#xff0c;满足各种外径尺寸的产品检测&#xff0c;囊括产线的所有规格&#xff0c;性价比更高的测径仪。 关键词&#xff1a;测径仪,范围可调测径仪,在线测径仪 引言 生产线中&#xff0c;各种外径尺寸的线材、棒材、管材都有生产&#xff…

【SAP NWDI】服务开启:SLD,CM,CMS(二)

一、启用System Landscape Directory 二、启用 NWDI using CMS

CAN的底层驱动

框架图 拆解链路模型 CAN子系统 can_controller Core 包含协议控制器和接收/发送移位寄存器。它可处理所有 ISO 11898-1: 2015 协议功能,并支持 11 位和 29 位标识符。

一、基础算法-快速排序

1.快速排序 快速排序主要利用了分治的思想&#xff0c;具体步骤为&#xff1a; step1 确定分界点&#xff0c;常用为q[left],q[right],q[mid]&#xff0c;也可以是随机的 step2 调整区间&#xff0c;将比分界点小的放左边&#xff0c;大的放右边 step3 利用递归处理左右两端 …

嵌入式Linux串口通信

嵌入式板子就和普通用的单片机比如stm32开发板&#xff0c;51开发板差不多&#xff0c;他们的串口都很类似&#xff0c;都是直接连上然后在PC机器上用串口软件打开就好了。 我使用的嵌入式开发板上面有8个rs485串口&#xff0c;2个rs232串口以及一个网口&#xff0c;刚开始开发…

代码随想录算法训练营第三十七天| LeetCode 738.单调递增的数字、总结

一、LeetCode 738.单调递增的数字 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html 状态&#xff1a;已解决 1.思路 如何求得小于等于N的最大单调递增的整数&#xff1f;98&am…

<计算机网络自顶向下> 多路复用与解复用

多路复用/解复用 端口号区分进程到进程多路解复用工作原理 解复用作用&#xff1a;TCP或者UDP实体采用哪些信息&#xff0c;将报文段的数据部分交给正确的socket&#xff0c;从而交给正确的进程主机收到IP数据报 每个数据报有源IP地址和目标地址每个数据报承载一个传输层报文段…

C++从入门到精通——const与取地址重载

const与取地址重载 前言一、const正常用法const成员函数问题const对象可以调用非const成员函数吗非const对象可以调用const成员函数吗const成员函数内可以调用其它的非const成员函数吗非const成员函数内可以调用其它的const成员函数吗总结 二、取地址及const取地址操作符重载概…

PPTX与PPT文件有什么区别?这2个办公技巧一定要知道!

每一次点击鼠标&#xff0c;每一次敲击键盘&#xff0c;我们都在与各种软件进行互动。其中&#xff0c;PPTX 和 PPT 无疑是职场中最常见的两种办公文档格式。那么&#xff0c;你是否清楚 PPTX 和 PPT 这两者之间的区别呢&#xff1f; 或许你会说&#xff0c;这不过是文件后缀名…

通过抖音短视频获客 只需要六步

抖音是当前最受欢迎的短视频平台之一&#xff0c;拥有庞大的用户群体和强大的社交矩阵&#xff0c;已经成为企业打造品牌口碑和快速获客的一种有效方式。那么&#xff0c;如何利用抖音短视频快速获客&#xff0c;打造品牌口碑呢&#xff1f;小马识途营销顾问简要分析如下&#…