说明:
本文重点是想使用autogen构建智能体,并且想要通过加载本地模型来构建,以灵活使用。但是autogen重点是以API调用支持openai, mistral等大模型使用的,对于使用国内的一些模型不是那么友好方便。然后在查找方法的过程中,找到了fastchat这样一个方法。
所以记录下结合使用的过程关键点。
(如果可以正常远程调用,请忽略)
一、fastchat与autogen简要介绍
1.1 autogen
utoGen是一个由Microsoft团队开发的开源框架,旨在简化大型语言模型(LLM)的工作流程编排和优化。这个框架特别适用于开发涉及对话自治性、代理数量和代理对话拓扑的下一代LLM应用。AutoGen的核心特点包括:
- 多代理对话框架:AutoGen允许使用多个代理进行对话和解决任务,这些代理是可定制和可对话的,并且可以无缝地允许人类参与。它们能在使用LLM、人类输入和工具的各种模式下运行2。
-
简化和自动化LLM工作流:AutoGen简化了复杂LLM工作流的编排、自动化和优化,最大化了LLM模型的性能,并克服了它们的弱点。它支持多样化的对话模式,适用于复杂的工作流程2。
-
模块化和可重用的代理:在AutoGen框架中,开发复杂的多代理对话系统只需两个步骤:定义一组代理,每个代理都有其角色和功能;定义代理之间的交互行为。这些代理是模块化且直观的,可组合且可重用4。
1.2 fastchat
FastChat是一个用于训练、部署和评估基于大型语言模型的聊天机器人的开放平台。这个平台的核心功能包括提供最先进的大型语言模型(LLM)的权重、训练代码和评估代码,例如Vicuna和FastChat-T5模型。此外,FastChat还提供了一个基于分布式多模型的服务系统,这个系统拥有Web界面,并且与OpenAI的RESTful API兼容12。
FastChat是由UC Berkeley主导的Large Model Systems Organization开源的,专门面向LLM的训练、推理和评估。通过这个平台,用户可以快速部署多模型的LLM服务,并且可以通过Web UI以及兼容OpenAI API的RESTful API来访问这些服务。
二、autogen使用本地模型方式
2.1 兼容 OpenAI API 的代理服务器
原理如下,任何提供与OpenAI 的 API兼容的 API 的代理服务器都可以与 AutoGen 一起使用。
这些代理服务器可以是基于云的,也可以在您的环境中本地运行。本文中采用的就是右侧local proxy server方式,即自己建立一个服务API,进行调用。
2.2 autogen代码配置
调用代码示例如下,其中 llm_config 就是我们要配置的大模型的信息。
import os
from autogen import ConversableAgent
# 创建一个名为 agent_with_number 的 ConversableAgent 对象
agent_with_number = ConversableAgent(
"agent_with_number",
system_message="你正在玩一个猜数字的游戏。你心里想的数字是53,我会尝试猜出来。如果我猜得太高,请说'太高';如果我猜得太低,请说'太低'。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
is_termination_msg=lambda msg: "53" in msg["content"], # 如果对方猜中了数字,终止对话
human_input_mode="NEVER", # 不需要人类输入
)
# 创建一个名为 agent_guess_number 的 ConversableAgent 对象
agent_guess_number = ConversableAgent(
"agent_guess_number",
system_message="我心里有一个数字,你要猜出来。如果我说'太高',你应该猜一个更小的数字。如果我说'太低',你应该猜一个更大的数字。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
human_input_mode="NEVER",
)
# agent_with_number 发起对话,并将 agent_guess_number 作为对话对象
result = agent_with_number.initiate_chat(
agent_guess_number,
message="我心里有一个1到100之间的数字。猜猜看吧!",
)
我们可以把这个config_list配置抽出来,放到一个json文件里面(如下图所示)。其中如果是官方支持的gpt4之类的,则要简单很多。如果是我们自己部署的模型服务,则需要重点提供base_url,同时保持 api_type=open_ai, api_key=NULL。
对于base_url,大家可以根据自己的情况,更新 http://127.0.0.1:8089部分,/v1必须要带上。
三、使用fastchat部署模型服务
3.1 fastchat安装
参考官网指导,直接pip安装即可。
pip3 install "fschat[model_worker,webui]"
3.2 启动服务(重点)
参考官网信息和其他博客的时候,会发现,要启动几个相关的服务和命令(如下所示),然而这几个之间什么关系,什么注意点,没有明确说明,这就是踩坑的地方,特此记录个人查阅了解的信息,说明一下。
python3 -m fastchat.serve.controller
python3 -m fastchat.serve.model_worker --model-path lmsys/vicuna-7b-v1.5
python3 -m fastchat.serve.openai_api_server --host localhost --port 8000
利用 FastChat 框架部署一个完整的模型服务主要分为三个部分,分别为: Controller , Server 以及多个 Worker 。这三者之间的关系如官方给出的下图所示:
(openai_api_server则在gradio server的位置,主要目的是包装成openai api的兼容模式)
3.2.1 启动控制器服务
fastchat.serve.controller 是 FastChat 框架中的控制器服务。控制器服务负责管理和调度模型工作进程以及其他相关组件。为了确保模型工作进程能够正常连接到控制器,您需要先启动控制器服务。
启动控制器服务通常可以通过以下命令完成,最好同时指定控制器服务的host和port配置,这样后面可以启动model_worker 跟 openai_api_server的时候,好对应起来。
python -m fastchat.serve.controller --host 127.0.0.1 --port 8087
其中,
--host 127.0.0.1:表示控制器将在本地网络接口上监听。
--port 8087:指定控制器监听的端口号。
启动成功之后,会有如下所示的提示
3.2.2 启动模型工作进程
这是负责加载模型并在后台处理实际推理请求的组件。它主要负责模型的具体运行逻辑。
启动模型工作进程命令如下:(另外打开一个terminal窗口)
python -m fastchat.serve.model_worker --model-path /xxx/ZhipuAI/glm-4-9b-chat/ --worker-address http://127.0.0.1:8087 --controller-address http://127.0.0.1:8087 --host=127.0.0.1 --port=8088
注意:
- controller-address:就是我们3.2.1中启动的控制器服务的地址,用于模型工作进程与控制器通信。
- worker-address:模型工作进程对外提供服务的地址,用于注册到控制器。(建议跟controller-address保持一致)
- host和port:指定 Uvicorn 服务器监听的地址和端口,用于接收实际请求。
- 通过这种指定的方式,可以确保模型工作进程正确地注册到控制器,并且 Uvicorn 服务器监听指定的端口。
执行命令之后,我们可以前往控制器启动的窗口,会发现有如下提示,说明注册成功:
2024-09-03 17:14:24 | INFO | controller | Register a new worker: http://127.0.0.1:8088
2024-09-03 17:14:24 | INFO | controller | Register done: http://127.0.0.1:8088, {'model_names': ['glm-4-9b-chat'], 'speed': 1, 'queue_length': 0}
2024-09-03 17:14:24 | INFO | stdout | INFO: 127.0.0.1:33239 - "POST /register_worker HTTP/1.1" 200 OK
然后,可以通过如下的方式,测试控制器与工作进程之间的连通性:
python3 -m fastchat.serve.test_message --model-name glm-4-9b-chat --worker-address http://127.0.0.1:8088 --controller-address http://127.0.0.1:8087
测试结果如下:
Human: Tell me a story with more than 1000 words.
Assistant: Of course! Here's a story for you:---
### The Enchanted Forest
In the heart of the ancient kingdom of Eldoria, there lay a
3.2.3 启动 OpenAI API 服务器
这是兼容OpenAI API并实际应用到autogen中的接口,同样也需要注册到控制器
python -m fastchat.serve.openai_api_server --host 127.0.0.1 --port 8089 --controller-address http://localhost:8087
然后就可以将 http://127.0.0.1:8089更新到 config_list 配置文件中了。
3.3 附加说明
3.3.1 直接启动
综上主要是为了记录探索过程中的一些过程点,如果想要直接快速使用的话,也可以参考官方网站的指导,直接采用如下命令启动,此时host与port均采用默认设置:
1、启动控制器
python -m fastchat.serve.controller
2、启动模型工作进程:
python -m fastchat.serve.model_worker --model-path chatglm2-6b
3、启动 RESTful API 服务器
python -m fastchat.serve.openai_api_server --host localhost --port 8000
3.3.2 错误提示
通常情况下,这将正常工作。但是,如果遇到像 这样的 错误,可以通过在 fastchat/protocol/api_protocol.py
和 fastchat/protocol/openai_api_protocol.py
中注释掉所有包含 finish_reason
的行来解决问题。修改后的代码如下所示:
class CompletionResponseChoice(BaseModel):
index: int
text: str
logprobs: Optional[int] = None
# finish_reason: Optional[Literal["stop", "length"]]
class CompletionResponseStreamChoice(BaseModel):
index: int
text: str
logprobs: Optional[float] = None
# finish_reason: Optional[Literal["stop", "length"]] = None
四、代码实践
测试的时候发现,API的方式响应很慢。下一篇文章将记录直接使用自定义模型加载类来实现的方式,相对会快一些。
测试代码如下:
# -*- coding: utf-8 -*-
from autogen.agentchat.conversable_agent import ConversableAgent
# 示例配置
llm_config = {
"config_list": [
{
"base_url": "http://localhost:8000/api/v1/",
"api_key": "NULL",
"model": "glm-4-9b-chat"
},
]
}
# 示例使用
def func_method_02(llm_config):
# 初始化您的代理
agent_a = ConversableAgent("脱口秀演员A",
llm_config=llm_config,
human_input_mode="NEVER")
agent_b = ConversableAgent("脱口秀演员B",
llm_config=llm_config,
human_input_mode="NEVER")
message = {
"role": "user",
"content": "大家好,欢迎大家来参加脱口秀大会,下面将由我们俩为大家讲一段儿脱口秀,感谢大家捧场了"
}
result = agent_a.initiate_chat(agent_b, message=message)
print("result: \n", result)
func_method_02(llm_config)