
书生大模型关卡任务-Lagent 自定义你的 Agent 智能体
Lagent 中关于工具部分的介绍文档位于。继承BaseAction类实现简单工具的run方法;或者实现工具包内每个子工具的功能简单工具的run方法可选被tool_api装饰;工具包内每个子工具的功能都需要被tool_api装饰下面我们将实现一个调用 MagicMaker API 以完成文生图的功能。首先,我们先来创建工具文件:然后,我们将下面的代码复制进入'dongman',# 动漫'guofe
1.环境配置
开发机选择 30% A100,镜像选择为 Cuda12.2-conda。
首先来为 Lagent 配置一个可用的环境。
# 创建环境 conda create -n agent_camp3 python=3.10 -y # 激活环境 conda activate agent_camp3 # 安装 torch conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y # 安装其他依赖包 pip install termcolor==2.4.0 pip install lmdeploy==0.5.2
接下来,我们通过源码安装的方式安装 lagent。
# 创建目录以存放代码 mkdir -p /root/agent_camp3 cd /root/agent_camp3 git clone https://github.com/InternLM/lagent.git cd lagent && git checkout 81e7ace && pip install -e . && cd .. pip install griffe==0.48.0
2.Lagent Web Demo 使用
接下来,我们将使用 Lagent 的 Web Demo 来体验 InternLM2.5-7B-Chat 的智能体能力。
首先,我们先使用 LMDeploy 部署 InternLM2.5-7B-Chat,并启动一个 API Server。
conda activate agent_camp3 lmdeploy serve api_server /share/new_models/Shanghai_AI_Laboratory/internlm2_5-7b-chat --model-name internlm2_5-7b-chat
然后,我们在另一个窗口中启动 Lagent 的 Web Demo。
cd /root/agent_camp3/lagent conda activate agent_camp3 streamlit run examples/internlm2_agent_web_demo.py
端口映射:
修改模型名称一栏为 internlm2_5-7b-chat
,修改模型 ip一栏为127.0.0.1:23333
。
输入后需要按下回车以确认!
然后,我们在插件选择一栏选择 ArxivSearch
,并输入指令“帮我搜索一下 MindSearch 论文”。
3.基于 Lagent 自定义智能体
Lagent 中关于工具部分的介绍文档位于 https://lagent.readthedocs.io/zh-cn/latest/tutorials/action.html 。
使用 Lagent 自定义工具主要分为以下几步:
- 继承
BaseAction
类 - 实现简单工具的
run
方法;或者实现工具包内每个子工具的功能 - 简单工具的
run
方法可选被tool_api
装饰;工具包内每个子工具的功能都需要被tool_api
装饰
下面我们将实现一个调用 MagicMaker API 以完成文生图的功能。
首先,我们先来创建工具文件:
cd /root/agent_camp3/lagent touch lagent/actions/magicmaker.py
然后,我们将下面的代码复制进入 /root/agent_camp3/lagent/lagent/actions/magicmaker.py
import json import requests from lagent.actions.base_action import BaseAction, tool_api from lagent.actions.parser import BaseParser, JsonParser from lagent.schema import ActionReturn, ActionStatusCode class MagicMaker(BaseAction): styles_option = [ 'dongman', # 动漫 'guofeng', # 国风 'xieshi', # 写实 'youhua', # 油画 'manghe', # 盲盒 ] aspect_ratio_options = [ '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16' ] def __init__(self, style='guofeng', aspect_ratio='4:3'): super().__init__() if style in self.styles_option: self.style = style else: raise ValueError(f'The style must be one of {self.styles_option}') if aspect_ratio in self.aspect_ratio_options: self.aspect_ratio = aspect_ratio else: raise ValueError(f'The aspect ratio must be one of {aspect_ratio}') @tool_api def generate_image(self, keywords: str) -> dict: """Run magicmaker and get the generated image according to the keywords. Args: keywords (:class:`str`): the keywords to generate image Returns: :class:`dict`: the generated image * image (str): path to the generated image """ try: response = requests.post( url='https://magicmaker.openxlab.org.cn/gw/edit-anything/api/v1/bff/sd/generate', data=json.dumps({ "official": True, "prompt": keywords, "style": self.style, "poseT": False, "aspectRatio": self.aspect_ratio }), headers={'content-type': 'application/json'} ) except Exception as exc: return ActionReturn( errmsg=f'MagicMaker exception: {exc}', state=ActionStatusCode.HTTP_ERROR) image_url = response.json()['data']['imgUrl'] return {'image': image_url}
最后,我们修改 /root/agent_camp3/lagent/examples/internlm2_agent_web_demo.py
来适配我们的自定义工具。
- 在
from lagent.actions import ActionExecutor, ArxivSearch, IPythonInterpreter
的下一行添加from lagent.actions.magicmaker import MagicMaker
- 在第27行添加
MagicMaker()
。
from lagent.actions import ActionExecutor, ArxivSearch, IPythonInterpreter + from lagent.actions.magicmaker import MagicMaker from lagent.agents.internlm2_agent import INTERPRETER_CN, META_CN, PLUGIN_CN, Internlm2Agent, Internlm2Protocol ... action_list = [ ArxivSearch(), + MagicMaker(), ]
接下来,启动 Web Demo,要求生成山水画
发现调用工具成功,但是没有生成图片链接,原因是Magic Maker没用了
4.自定义Agent
参考:
图片生成 API 文档 | 讯飞开放平台文档中心 (xfyun.cn)
我们编写工具(密钥需要在科大讯飞申请)/root/agent_camp3/lagent/lagent/actions/imagecreator.py:
import json
import requests
from lagent.actions.base_action import BaseAction, tool_api
from lagent.schema import ActionReturn, ActionStatusCode
import time
from datetime import datetime
from wsgiref.handlers import format_date_time
from time import mktime
import hashlib
import base64
import hmac
from urllib.parse import urlencode
import json
from PIL import Image
from io import BytesIO
class AssembleHeaderException(Exception):
def __init__(self, msg):
self.message = msg
class Url:
def __init__(this, host, path, schema):
this.host = host
this.path = path
this.schema = schema
pass
# calculate sha256 and encode to base64
def sha256base64(data):
sha256 = hashlib.sha256()
sha256.update(data)
digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
return digest
def parse_url(requset_url):
stidx = requset_url.index("://")
host = requset_url[stidx + 3:]
schema = requset_url[:stidx + 3]
edidx = host.index("/")
if edidx <= 0:
raise AssembleHeaderException("invalid request url:" + requset_url)
path = host[edidx:]
host = host[:edidx]
u = Url(host, path, schema)
return u
# 生成鉴权url
def assemble_ws_auth_url(requset_url, method="GET", api_key="", api_secret=""):
u = parse_url(requset_url)
host = u.host
path = u.path
now = datetime.now()
date = format_date_time(mktime(now.timetuple()))
# print(date)
# date = "Thu, 12 Dec 2019 01:57:27 GMT"
signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(host, date, method, path)
# print(signature_origin)
signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
digestmod=hashlib.sha256).digest()
signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
api_key, "hmac-sha256", "host date request-line", signature_sha)
authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
# print(authorization_origin)
values = {
"host": host,
"date": date,
"authorization": authorization
}
return requset_url + "?" + urlencode(values)
# 生成请求body体
def getBody(appid,text):
body= {
"header": {
"app_id": appid,
"uid":"123456789"
},
"parameter": {
"chat": {
"domain": "general",
"temperature":0.5,
"max_tokens":4096
}
},
"payload": {
"message":{
"text":[
{
"role":"user",
"content":text
}
]
}
}
}
return body
# 发起请求并返回结果
def main(text,appid,apikey,apisecret):
host = 'http://spark-api.cn-huabei-1.xf-yun.com/v2.1/tti'
url = assemble_ws_auth_url(host,method='POST',api_key=apikey,api_secret=apisecret)
content = getBody(appid,text)
print(time.time())
response = requests.post(url,json=content,headers={'content-type': "application/json"}).text
print(time.time())
return response
#将base64 的图片数据存在本地
def base64_to_image(base64_data, save_path):
# 解码base64数据
img_data = base64.b64decode(base64_data)
# 将解码后的数据转换为图片
img = Image.open(BytesIO(img_data))
# 保存图片到本地
img.save(save_path)
# 解析并保存到指定位置
def parser_Message(message):
data = json.loads(message)
# print("data" + str(message))
code = data['header']['code']
if code != 0:
print(f'请求错误: {code}, {data}')
else:
text = data["payload"]["choices"]["text"]
imageContent = text[0]
# if('image' == imageContent["content_type"]):
imageBase = imageContent["content"]
imageName = data['header']['sid']
savePath = f"/root/agent_camp3/lagent/tmp_dir/{imageName}.jpg"
base64_to_image(imageBase,savePath)
print("图片保存路径:" + savePath)
def get_path(desc):
#运行前请配置以下鉴权三要素,获取途径:https://console.xfyun.cn/services/tti
APPID =''
APISecret = ''
APIKEY = ''#!!!!!!!!!!!!这里要填入科大讯飞对应服务的密钥
res = main(desc,appid=APPID,apikey=APIKEY,apisecret=APISecret)
# print(res)
#保存到指定位置
parser_Message(res)
# print(res)
data = json.loads(res)
save_path = f"http://127.0.0.1:7860/imgs/{data['header']['sid']}.jpg"
return save_path
class ImageCreator(BaseAction):
def __init__(self):
super().__init__()
@tool_api
def create_image(self, keywords: str) -> dict:
"""Create an image based on the input text using the specified API.
Args:
text (:class:`str`): the text to generate image
Returns:
:class:`dict`: the generated image information
* image_path (str): path to the generated image
"""
try:
save_path=get_path(keywords)
return {'image': save_path}
except Exception as exc:
print(exc)
return ActionReturn(
errmsg=f'ImageCreator exception: {exc}',
state=ActionStatusCode.HTTP_ERROR)
if __name__ == "__main__":
imc=ImageCreator()
print(imc.create_image("山水画"))
这里和Magic Maker不同的是文生图直接返回的是图片的二进制码,所以我们把生成的图片存到目录/root/agent_camp3/lagent/tmp_dir/中,然后我们要把该目录的图片以get请求的方式映射出来,编写、运行如下脚本/root/agent_camp3/app.py:
from flask import Flask, send_from_directory, abort
app = Flask(__name__)
# 设置图片存储目录
img_dir = '/root/agent_camp3/lagent/tmp_dir/'
@app.route('/imgs/<path:filename>')
def img_proxy(filename):
"""
Serve images from the specified directory.
"""
return send_from_directory(img_dir, filename)
if __name__ == '__main__':
# 运行 Flask 应用
app.run(host='127.0.0.1', port=7860)
这样,我们就能访问http://127.0.0.1:7860/imgs/ +图片文件名(如cht000b897f@dx1924cd6c77bb894550.jpg)访问到图片。
最后修改web_demo:
运行:
端口映射:
再次让模型调用工具:
点击超链:
发现成功按要求生成图片。
更多推荐
所有评论(0)