Agently 3.0 指南
[重要]
Agently AI开发框架中文首页改版已经完成,模型切换、AgenticRequest、Workflow全新教程文档全面更新,请访问:Agently.cn查看
[重要]
我们将很快重新编写仓库首页,以告诉您更多关于我们近期工作的内容,请耐心等待。
[展示仓库]Agently Daily News Collector: 英文 | 新闻汇总报告生成器开源项目
[热门]
中文版由浅入深开发文档:点此访问,一步一步解锁复杂LLMs应用开发技能点
📥 使用方法:
pip install -U Agently
💡 点子 / Bug报告: 在此报告问题
📧 发送邮件给我们: developer@agently.cn
👾 Discord 群组:
点击这里加入 或扫描下方二维码
💬 微信群组(加入微信群):
点击这里申请 或扫描下方二维码
如果您喜欢这个项目,请给我们一个⭐️,谢谢。
资源菜单
Colab文档:
代码示例:
在许多不同领域中构建代理:
或者,在代码逻辑中调用代理实例能力以提供帮助:
探索更多: 访问演示操场
安装与准备
安装Agently Python软件包:
pip install -U Agently
然后我们准备好了!
什么是 Agently?
Agently是一个开发框架,可帮助开发人员非常快速地构建AI代理原生应用。
您可以以极其简单的方式在代码中使用和构建AI代理。
您可以创建AI代理实例,然后像调用函数一样与它交互,只需下面极少几行代码。
点击下方运行按钮,见证奇迹。就是这么简单:
# 导入并初始化设置
import Agently
agent = Agently.create_agent()
agent\
.set_settings("current_model", "OpenAI")\
.set_settings("model.OpenAI.auth", { "api_key": "" })
# 像调用函数一样与代理实例交互
result = agent\
.input("给我三个单词")\
.output([("字符串", "一个单词")])\
.start()
print(result)
['苹果', '香蕉', '胡萝卜']
并且,您可能注意到,当我们打印result
的值时,值是一个列表
,正如我们输入到.output()
中的参数格式一样。
在Agently框架中我们做了很多这样的工作,使应用开发人员更容易将代理实例集成到他们的业务代码中。这将允许应用开发人员专注于如何构建他们的业务逻辑,而不是搞清楚如何迎合语言模型或如何让模型满意。
简单易用: 以一种令人难以置信的简单方式开发AI代理原生应用模块
什么是AI代理原生应用?
当我们开始在代码中使用AI代理来帮助我们处理业务逻辑时,我们可以很容易地感受到,这与传统的软件开发方式一定有些不同。但到底有什么不同呢?
我认为关键点是使用AI代理来解决问题,而不是人为编写的代码逻辑。
在AI代理原生应用中,我们将AI代理实例放入我们的代码中,然后我们用自然语言或自然语言类似的表达来要求它执行/解决问题。
“问-得到响应”取代了传统的“定义问题 - 编程 - 编码实现”。
这真的像我们说的那样简单吗?
当然!Agently框架提供了与AI代理实例交互的简单方法,使应用模块开发快速而简单。
下面是两个完全不同领域的CLI应用演示,但都由Agently框架提供支持的64行代码构建。
演示1: SQL生成器
演示视频
https://github.com/Maplemx/Agently/assets/4413155/b7d16592-5fdc-43c0-a14c-f2272c7900da
代码
import Agently
agent_factory = Agently.AgentFactory(is_debug = False)
agent_factory\
.set_settings("current_model", "OpenAI")\
.set_settings("model.OpenAI.auth", { "api_key": "" })
agent = agent_factory.create_agent()
meta_data = {
"table_meta" : [
{
"table_name": "user",
"columns": [
{ "column_name": "user_id", "desc": "用户身份", "value type": "Number" },
{ "column_name": "gender", "desc": "用户性别", "value type": ["男", "女"] },
{ "column_name": "age", "desc": "用户年龄", "value type": "Number" },
{ "column_name": "customer_level", "desc": "客户账户等级", "value type": [1,2,3,4,5] },
]
},
{
"table_name": "order",
"columns": [
{ "column_name": "order_id", "desc": "订单身份", "value type": "Number" },
{ "column_name": "customer_user_id", "desc": "客户身份,与user_id相同", "value type": "Number" },
{ "column_name": "item_name", "desc": "订单中的商品名称", "value type": "String" },
{ "column_name": "item_number", "desc": "购买该商品的数量", "value type": "Number" },
{ "column_name": "price", "desc": "每个商品的价格", "value type": "Number" },
{ "column_name": "date", "desc": "订单发生的日期", "value type": "Date" },
]
},
]
}
is_finish = False
while not is_finish:
question = input("您想知道什么: ")
show_thinking = None
while str(show_thinking).lower() not in ("y", "n"):
show_thinking = input("您想观察思考过程吗? [Y/N]: ")
show_thinking = False if show_thinking.lower == "n" else True
print("[生成中...]")
result = agent\
.input({
"table_meta": meta_data["table_meta"],
"question": question
})\
.instruct([
"根据元数据:{table_meta}生成SQL以查询数据库并回答问题:{question}",
"输出语言: 英文",
])\
.output({
"thinkings": ["字符串", "逐步解决问题的思维步骤"],
"SQL": ("字符串", "最终的SQL"),
})\
.start()
if show_thinking:
thinking_process = "\n".join(result["thinkings"])
print("[思考过程]\n", thinking_process)
print("[SQL]\n", result["SQL"])
while str(is_finish).lower() not in ("y", "n"):
is_finish = input("您要退出吗?[Y退出 / N继续]: ")
is_finish = False if is_finish.lower() == "n" else True
演示2: 角色创建者(与角色聊天)
import Agently
agent_factory = Agently.AgentFactory(is_debug = False)
agent_factory\
.set_settings("current_model", "OpenAI")\
.set_settings("model.OpenAI.auth", { "api_key": "" })
writer_agent = agent_factory.create_agent()
roleplay_agent = agent_factory.create_agent()
# 创建角色
character_desc = input("用几个词描述您想与之交谈的角色: ")
is_accepted = ""
suggestions = ""
last_time_character_setting = {}
while is_accepted.lower() != "y":
is_accepted = ""
input_dict = { "character_desc": character_desc }
if suggestions != "":
input_dict.update({ "suggestions": suggestions })
input_dict.update({ "last_time_character_setting": last_time_character_setting })
setting_result = writer_agent\
.input(input_dict)\
.instruct([
"根据{input.character_desc}设计一个角色。",
"如果存在{input.suggestions},则根据{input.suggestions}重新编写{input.last_time_character_setting}。",
])\
.output({
"name": ("String",),
"age": ("Number",),
"character": ("String", "关于这个角色的角色描述,他/她喜欢采取的行动,他/她的行为习惯等。"),
"belief": ("String", "这个角色的信仰或座右铭"),
"background_story": [("String", "这个角色的背景故事的一部分")],
"response_examples": [{ "Question": ("String", "用户可能问这个角色的问题"), "Response": ("String", "这个角色会说的简短回应。") }],
})\
.on_delta(lambda data: print(data, end=""))\
.start()
while is_accepted.lower() not in ("y", "n"):
is_accepted = input("您对这个角色的设定满意吗? [Y/N]: ")
if is_accepted.lower() == "n":
suggestions = input("你对这个设定有一些建议吗?(留白将重新设定所有设置):")
if suggestions != "":
last_time_character_settings = setting_result
print("[开始加载角色设置到代理...]")
# 加载角色到代理然后与之聊天
for key, value in setting_result.items():
roleplay_agent.set_role(key, value)
print("[加载完成。开始聊天吧](输入'#exit'退出)")
roleplay_agent.active_session()
chat_input = ""
while True:
chat_input = input("你: ")
if chat_input == "#exit":
break
print(f"{ setting_result['name'] }: ", end="")
roleplay_agent\
.input(chat_input)\
.instruct("根据您的{ROLE}设置回应{chat_input}。像在聊天中那样回应,而不是查询或请求!")\
.on_delta(lambda data: print(data, end=""))\
.start()
print("")
print("再见👋~")
易于增强和更新: 使用插件增强AI代理而不是重建一个全新的代理
为什么Agently如此重视插件增强?
OpenAI的Lilian Weng关于LLM驱动的自主代理的文章为AI代理的基本结构提供了一个非常好的概念。但该文章并没有解释如何构建一个AI代理。
一些很棒的项目如LangChain和Camel-AI展示了它们关于如何构建AI代理的想法。在这些项目中,根据代理的任务或思维过程,代理被分为许多不同的类型。
但如果我们遵循这些构建代理的思路,这意味着如果我们想要让一个新代理在不同领域工作就必须构建一个全新的代理。即使所有的项目提供一个ChatAgent基础类或类似的东西,新的代理子类仍将被构建,越来越多特定类型的代理将被生产。随着代理类型数量的增加,总有一天,砰!将有太多类型的代理供开发人员选择以及代理平台去管理。它们将难以搜索,难以选择,难以管理和难以更新。 所以 Agently 团队一直在思考是否有更好的方法来增强代理并使所有开发者都能轻松参与。
此外,目前 AI 代理的结构和组件看起来简单易构建。但如果我们往前看,每个组件都会变得更加复杂(例如内存管理),并且会添加越来越多的新组件(例如传感器)。
如果我们停止像一个不可分割的整体构建代理,而是将其分离成一个管理运行时上下文数据和运行时过程的中心结构,并通过不同的插件在运行时过程中增强其能力,使其适用于不同的使用场景会怎么样?“分而治之”,就像著名的工程箴言所说的那样。
我们在 Agently 3.0 中实现了这一点,而当 Agently 3.0 进行 alpha 测试时,我们很高兴看到这种插件增强设计不仅解决了重建全新代理的问题,还帮助每个组件开发人员仅专注于该组件关心的目标和问题,而不会分心。这使得组件插件开发非常容易,代码也很简单。
Agently 框架能够帮助构建的代理结构
示例 1: 代理组件源代码 - 角色
下面是一个示例,展示了如何在 Agently 框架中开发代理组件插件。由于运行时上下文数据管理工作由框架完成,插件开发人员可以使用许多运行时工具来帮助构建代理组件插件。这使工作非常容易。
⚠️:下面的代码是一个插件代码示例,它在框架中工作,无法单独运行。
from .utils import ComponentABC
from Agently.utils import RuntimeCtxNamespace
# 创建符合抽象基类的插件类
class Role(ComponentABC):
def __init__(self, agent: object):
self.agent = agent
# 框架通过并传递运行时上下文和存储,组件可以使用它们
self.role_runtime_ctx = RuntimeCtxNamespace("role", self.agent.agent_runtime_ctx)
self.role_storage = self.agent.global_storage.table("role")
# 定义此组件的方法
# 更新运行时上下文,遵循代理实例生命周期
def set_name(self, name: str, *, target: str):
self.role_runtime_ctx.set("NAME", name)
return self.agent
def set(self, key: any, value: any=None, *, target: str):
if value is not None:
self.role_runtime_ctx.set(key, value)
else:
self.role_runtime_ctx.set("DESC", key)
return self.agent
def update(self, key: any, value: any=None, *, target: str):
if value is not None:
self.role_runtime_ctx.update(key, value)
else:
self.role_runtime_ctx.update("DESC", key)
return self.agent
def append(self, key: any, value: any=None, *, target: str):
if value is not None:
self.role_runtime_ctx.append(key, value)
else:
self.role_runtime_ctx.append("DESC", key)
return self.agent
def extend(self, key: any, value: any=None, *, target: str):
if value is not None:
self.role_runtime_ctx.extend(key, value)
else:
self.role_runtime_ctx.extend("DESC", key)
return self.agent
# 或保存到/从存储加载,保持数据在文件存储或数据库中
def save(self, role_name: str=None):
if role_name == None:
role_name = self.role_runtime_ctx.get("NAME")
if role_name != None and role_name != "":
self.role_storage\
.set(role_name, self.role_runtime_ctx.get())\
.save()
return self.agent
else:
raise Exception("[Agent Component: Role] Role 属性 'NAME' 必须在保存前声明。使用 .set_role_name() 指定它。")
def load(self, role_name: str):
role_data = self.role_storage.get(role_name)
for key, value in role_data.items():
self.role_runtime_ctx.update(key, value)
return self.agent
# 将数据传递到前缀阶段的标准插槽请求
def _prefix(self):
return {
"role": self.role_runtime_ctx.get(),
}
# 导出组件插件接口以在代理运行时过程中调用
def export(self):
return {
"early": None, # 在早期阶段调用的方法
"prefix": self._prefix, # 在前缀阶段调用的方法
"suffix": None, # 在后缀阶段调用的方法
# 应用开发人员可以在代理实例中使用的别名
# 例如:
# "alias": { "set_role_name": { "func": self.set_name } }
# => agent.set_role_name("Alice")
"alias": {
"set_role_name": { "func": self.set_name },
"set_role": { "func": self.set },
"update_role": { "func": self.update },
"append_role": { "func": self.append },
"extend_role": { "func": self.extend },
"save_role": { "func": self.save },
"load_role": { "func": self.load },
},
}
# 导出到插件目录自动扫描器
def export():
return ("Role", Role)
示例 2: 在包外安装插件
Agently 框架还允许插件开发人员将其插件打包在框架主包之外,并单独将其插件包分享给其他开发人员。那些想使用特定插件的开发人员只需下载插件包,将文件解压缩到他们的工作文件夹中,然后轻松安装插件。
下面的代码将展示这种安装的简便性。
⚠️:下面的代码是一个插件安装示例,仅当您在工作文件夹中解压插件文件夹时才有效。
import Agently
# 从插件文件夹导入安装方法
from session_plugin import install
# 然后安装
install(Agently)
# 就这么简单
# 现在您的代理可以使用由新插件增强的新功能
这里还有一个真实案例,当 Agently v3.0.1 存在一个使会话组件不可用的问题时,我们使用插件包更新修复了该错误,而不必更新整个框架包。
想深入了解吗?
好的。这是关于 Agently AI 代理开发框架的总体介绍。
如果您想深入了解,还可以访问这些文档/链接:
- Agently 3.0 应用开发手册
- Agently 3.0 插件开发手册(正在编写中)
- Agently 3.0 示例游乐场
如果你喜欢我们的工作,不要忘了给这个仓库点个 ⭐️。
谢谢,祝你编码愉快!