跳转至

Agently

极致顺滑的AI应用开发心流体验,原来AI应用开发可以这么简单

易用、灵活、高效
用3.5+级别的低价模型平替原本只能用GPT-4完成的工作,成本立减99%
支持各类主流模型随意切换不冲击业务逻辑,帮助开发者提升模型输出控制能力
代码级编排复杂工作流,构建复杂AI应用场景
符合工程开发直觉的开发语法设计打磨,让开发者专注在业务表达,屏蔽无关思考,文思泉涌,根本停不下来
pip install -U Agently
git clone git@github.com:Maplemx/Agently.git

> 阅读开发教程 > GitHub项目页面 > 加入交流微信群

框架特性


  • AnyModel 任意模型无感切换


    • 与应用代码表达解耦,任意切换基础模型不冲击业务逻辑

    • 支持海量主流商用模型API、本地私有化部署模型

    • 支持多模型混用协同,不同模型分工处理复杂问题

    • 支持各类模型流式输出、协程异步请求,方便工程复杂编排

    查看支持模型列表

  • AgenticRequest 增强模型输出控制能力


    • 遵循工程开发习惯设计的模型请求语法,直观易用符合直觉

    • 强大的模型输出控制能力,结构化数据输出成功率超过90%

    • 支持意图识别、思维链、角色控制、知识插入等应用场景

    • 无需特殊接口即可获得工具调用、ReAct等高级能力

    查看手把手提升模型控制能力教程

  • Workflow 强大又易用的工作流编程方案


    • 精心打磨的工作流编程开发语法,紧跟思路开发顺畅不卡壳

    • 支持环状结构、并行分支、条件分发等复杂工作流结构

    • 支持数据块间时序传递、工作流全局传递、跨工作流传递

    • 对比知名AI开发框架友商,能力毫不逊色甚至更强

    查看Agently Workflow详细介绍

  • Agently Instant 兼顾结构化输出和流式输出


    • 流式输出结构化输出二者可以兼得

    • 在多分支复杂任务中,输出即可用,快人一步,执行效率提升高达55%

    • 提供监听器和Generator不同模式,兼容适配不同开发场景

    • 精心设计的定位语法配合Agently Output结构化控制能力,追踪复杂结构任意位置的键值

    查看Agently Instant用法及实验测试

代码示例


Python代码
"""创建Agent实例"""
import Agently
agent = (
    Agently.create_agent()
        # 支持通过配置快速切换多种模型
        # 将代码的业务逻辑表达和模型配置格式依赖解耦
        .set_settings("current_model", "OpenAI")
        .set_settings("model.OpenAI.auth", { "api_key": "******" })
        # 支持设置Proxy进行前向代理
        .set_proxy("http://127.0.0.1:7890")
)
"""进行基础请求"""
result = (
    agent
        # 支持str格式输入
        .input("给我输出3个单词和2个句子")
        # 支持Key-Value格式输入
        .instruct("输出语言", "中文")
        # 支持dict格式输入
        # 并且通过框架特有的(<type>, <desc>)语法格式描述生成元素
        .output({
            "单词": [("str", )], # 没有<desc>可省略
            "句子": ("list", ),
        })
        .start()
)
print(result)
运行结果
{'单词': ['苹果', '电脑', '学习'], '句子': ['我喜欢吃苹果。', '他用电脑工作。']}
Python代码
"""创建Agent实例"""
import Agently
agent = (
    Agently.create_agent()
        .set_settings("current_model", "ZhipuAI")
        .set_settings("model.ZhipuAI.auth", { "api_key": "******" }
)
"""进行Agent实例设定"""
( agent
      .set_role("职业", "一个温柔、耐心的少儿陪伴专家")
      .set_user_info("姓名", "Max")
      .append_user_info(
            "关键信息",
            [
                "我今年7岁",
                "我比较喜欢听别人用讲故事的方式跟我解释一件事情",
                "对于新的概念,我比较喜欢通过类比我已经知道的事情来学习",
                "我对于小学校园、动物园、游乐场比较熟悉",
                "我有时候会玩例如我的世界、模拟城市这样的电子游戏",
            ]
        )
)
"""发起请求"""
print(agent.input("代码编程能做什么?").start())  
运行结果
嗨,Max!编程就像是在创造一个故事或者一个世界,不过用的是计算机能理解的“语言”。编程可以做很多有趣和有用的事情哦:

1. **创造游戏**:就像你玩的“我的世界”和“模拟城市”,这些游戏都是通过编程来创造的。你可以用编程来设计自己的游戏,决定游戏里面的规则和故事。

2. **解决问题**:编程能帮助解决数学问题,比如计算你的成绩或者帮你理解数学概念。

3. **制作动画和电影**:你看过动画片吗?很多动画电影和电视节目都是用特殊的编程软件制作的,让角色动起来。

4. **控制机器人**:如果你喜欢去动物园,想象一下如果你能通过编程控制一个机器人,让它去探索动物的生活,是不是很有趣?

5. **网站和应用程序**:像你浏览的网页,或者玩的游戏,都是程序员用编程语言创造出来的。

6. **学习新事物**:编程能帮你通过类比学习新概念,比如你可以把编程比作是搭建一个游乐场,每条代码就像是你用的积木,一块一块搭建成一个完整的游乐场。

7. **分享故事**:如果你喜欢听故事,编程也可以帮你把故事变成互动的形式,让故事更加生动有趣。

编程就像是一种魔法,能把你脑海中的想象变成现实。怎么样,是不是很酷? 
Python代码
"""创建Agent实例"""
import Agently
agent = (
    Agently.create_agent()
        .set_settings("current_model", "ERNIE") #文心一言
        .set_settings("model.ERNIE.auth", { "aistudio": "******" })
)
"""设定Agent实例可调用的工具"""
( agent
    .use_public_tools(["search"])
    # 设定Proxy(如果有需要)
    .set_tool_proxy("http://127.0.0.1:7890")
)
"""发起请求"""
print(agent.input("什么是Agently框架?").start())  
运行结果
Agently是一个帮助大语言模型(LLM)应用开发者快速构建AI agent原生应用的开发框架。

它允许插件开发者将插件打包在框架主包之外,并单独分享他们的插件包给其他开发者。

开发者只需要下载插件包,将文件解压到他们的工作文件夹中,然后轻松安装插件。

Agently还提供了创建和管理基于大语言模型的Agent实例的功能,并能管理他们的人设和记忆,适用于客服机器人、角色扮演机器人等应用。

此外,Agently还不断更新版本,为开发者提供更多便利的功能和工具。

更多信息可以参考Agently的GitHub官方仓库:[Agently](https://github.com/Maplemx/Agently) 
Python代码
"""创建Agent实例"""
import Agently
agent = (
    Agently.create_agent()
        .set_settings("current_model", "Claude")
        .set_settings("model.Claude.auth", { "api_key": "******" }
)
"""定义并注册自定义工具"""
# 自定义工具函数及依赖
from datetime import datetime
import pytz
def get_current_datetime(timezone):
    tz = pytz.timezone(timezone)
    return datetime.now().astimezone(tz)
# 自定义工具信息字典
tool_info = {
    "tool_name": "get_now",
    "desc": "get current data and time",
    "args": {
        "timezone": (
            "str",
            "[*Required] Timezone string used in pytz.timezone() in Python"
        )
    },
    "func": get_current_datetime
}
# 向Agent实例注册自定义工具
agent.register_tool(
    tool_name = tool_info["tool_name"],
    desc = tool_info["desc"],
    args = tool_info["args"],
    func = tool_info["func"],
)
"""发起请求"""
print(agent.input("我在北京,现在几点了?").start())  
运行结果
根据您提供的信息,在北京时间 2024年4月6日 21点43分22秒。如需了解更多相关信息,您可以查阅 [北京时间](https://time.is/Beijing) 网站。
Python代码
"""创建Agent实例"""
import Agently
agent = (
    Agently.create_agent()
        .set_settings("current_model", "Google")
        .set_settings("model.Google.auth", { "api_key": "******" }
)
"""声明流式输出结果的处理方法"""
@agent.on_event("delta")
def delta_event_handler(data):
    print(">", data, end="")
"""发起请求"""
agent.input("请输出一段话。").start()

# 也支持Generator输出
generator = agent.input("请输出一段话。").get_generator()
for event, data in generator:
    if event == "start":
        print("开始输出结果:")
    if event == "delta":
        print(data, end="", flush=True)
    if event == "done":
        print("----------")        
运行结果
> 在广袤无垠的宇宙中,一颗蔚蓝色的星球默默旋转
> 着,那是我们的家园——地球。它是一个充满生机与奇迹的世界,从 towering mountaintops 到 deepest oceans,无处不展现着大
> 自然的鬼斧神工。地球是我们赖以生存的家园,是我们生命和梦想的摇篮,值得我们珍惜和保护。
Python代码
"""创建Agent实例和Workflow实例"""
import Agently
agent = (
    Agently.create_agent()
        .set_settings("current_model", "OAIClient")
        .set_settings("model.OAIClient.url", "https://api.moonshot.cn/v1")
        .set_settings("model.OAIClient.options", { "model": "moonshot-v1-8k" })
        .set_settings("model.OAIClient.auth", { "api_key": "********" })
)
workflow = Agently.Workflow()
"""创建执行块(Chunk)"""
# 用户输入块
@workflow.chunk()
def user_input(inputs, storage):
    return input("[User]: ")

# Agent回复块
@workflow.chunk()
def assistant_reply(inputs, storage):
    chat_history = storage.get("chat_history") or []
    reply = (
        agent
            .chat_history(chat_history)
            .input(inputs["default"])
            .start()
    )
    print("[Assistant]: ", reply)
    return reply

# 对话记录更新块
@workflow.chunk()
def update_chat_history(inputs, storage):
    chat_history = storage.get("chat_history", [])
    chat_history.append({ "role": "user", "content": inputs["user_input"] })
    chat_history.append({ "role": "assistant", "content": inputs["assistant_reply"] })
    storage.set("chat_history", chat_history)
    return

# 道别块
@workflow.chunk()
def goodbye(inputs, storage):
    print("Bye~👋")
    return

# 取出对话记录块
@workflow.chunk()
def get_all_chat_history(inputs, storage):
    return storage.get("chat_history")

"""连接执行块"""
workflow.connect_to("user_input")
(
    workflow.chunks["user_input"]
        .if_condition(lambda return_value, storage: return_value == "#exit")
            .connect_to("goodbye")
            .connect_to("get_all_chat_history")
            .connect_to("end")
        .else_condition()
            .connect_to("assistant_reply")
)
workflow.chunks["user_input"].connect_to("update_chat_history.user_input")
workflow.chunks["assistant_reply"].connect_to("update_chat_history.assistant_reply")
workflow.chunks["update_chat_history"].connect_to("user_input")

"""获取工作流Mermaid代码(可绘图)"""
print(workflow.draw())

"""启动工作流"""
"""将需要输出的数据连接到`end`块即可获得返回结果"""
chat_history = workflow.start()
print(chat_history["default"])
%%{ init: { 'flowchart': { 'curve': 'linear' }, 'theme': 'neutral' } }%%
%% Rendered By Agently %%
flowchart LR
classDef chunk_style fill:#fbfcdb,stroke:#666,stroke-width:1px,color:#333;
classDef condition_chunk_style fill:#ECECFF,stroke:#9370DB,stroke-width:1px,color:#333;
classDef loop_style fill:#f5f7fa,stroke:#666,stroke-width:1px,color:#333,stroke-dasharray: 5 5
    START("START"):::chunk_style -.-> |"#42; -->-- default"| user_input("user_input"):::chunk_style
    user_input("user_input"):::chunk_style -.-> |"#42; -->-- default"| f2ae2b1d-7d5a-5790-ae34-89c833ac5088::chunk::7{{"Condition"}}:::condition_chunk_style
    f2ae2b1d-7d5a-5790-ae34-89c833ac5088::chunk::7{{"Condition"}}:::condition_chunk_style -.-> |"#42; -- ◇ -- default"| goodbye("goodbye"):::chunk_style
    goodbye("goodbye"):::chunk_style -.-> |"#42; -->-- default"| get_all_chat_history("get_all_chat_history"):::chunk_style
    get_all_chat_history("get_all_chat_history"):::chunk_style -.-> |"#42; -->-- default"| END("END"):::chunk_style
    f2ae2b1d-7d5a-5790-ae34-89c833ac5088::chunk::7{{"Condition"}}:::condition_chunk_style -.-> |"#42; -- ◇ -- default"| assistant_reply("assistant_reply"):::chunk_style
    user_input("user_input"):::chunk_style -.-> |"#42; -->-- user_input"| update_chat_history("update_chat_history"):::chunk_style
    assistant_reply("assistant_reply"):::chunk_style -.-> |"#42; -->-- assistant_reply"| update_chat_history("update_chat_history"):::chunk_style
    update_chat_history("update_chat_history"):::chunk_style -.-> |"#42; -->-- default"| user_input("user_input"):::chunk_style
Python代码
import datetime
import Agently
agent = (
    Agently.create_agent()
        #.set_setting(...)
)

# 使用监听器监听新引入的instant事件
@agent.on_event("instant")
def instant_handler(data):
    # 返回的事件数据结构:
    # `key`: <str> 当前正在输出的键(采用Agently Instant表达方法)
    # `indexes`: <list> 如果当前正在输出的键路径中存在数组,`indexes`里会提供当前输出
    #                   是路径中数组的第几项
    # `delta`: <any> 当前正在输出的键值,如果键值类型是str,此字段更新每次添加的新内容
    #                否则只在键值完全生成完毕后抛出事件,此时字段值和`value`字段值一致
    # `value`: <any> 当前正在输出的键值,如果键值类型是str,此字段更新当前已生成的全量值
    #                否则只在键值完全生成完毕后抛出事件,此时字段值和`delta`字段值一致
    # `complete_value`: <any> 在当前事件抛出时,已经输出的结构化数据的全量内容

    # 输出Instant模式过程结果和输出时间
    print(datetime.now(), data["key"], data["indexes"], data["delta"])

result = (
    agent
        # 使用.use_instant()开启instant模式
        # 3.4.0.3版本之后可以省去此步
        .use_instant()
        .input("Generate 3 other words, then use those 3 words to make a sentence, then generate 4 numbers.")
        # 使用Agently Output语法定义一个复杂结构数据
        .output({
            "words": [("str", )],
            "sentence": ("str", ),
            "numbers": [{ "value": ("int", ) }]
        })
        .start()
)
# 输出最终结果和完成时间
print(datetime.now(), result)
运行结果
Instant模式输出:
2024-11-03 02:20:01.650752 words.[].$delta [0] cat
2024-11-03 02:20:01.831325 words.[].$delta [1] mouse
2024-11-03 02:20:01.835427 words.[] [0] cat
2024-11-03 02:20:01.849140 words.[].$delta [2] run
2024-11-03 02:20:01.850624 words.[] [1] mouse
2024-11-03 02:20:01.912867 words [] ['cat', 'mouse', 'run']
2024-11-03 02:20:01.913157 words.[] [2] run
2024-11-03 02:20:01.962901 sentence.$delta [] The
2024-11-03 02:20:01.980559 sentence.$delta []  cat
2024-11-03 02:20:01.998184 sentence.$delta []  chased
2024-11-03 02:20:02.015376 sentence.$delta []  the
2024-11-03 02:20:02.032466 sentence.$delta []  mouse
2024-11-03 02:20:02.050336 sentence.$delta []  as
2024-11-03 02:20:02.088583 sentence.$delta []  it
2024-11-03 02:20:02.091482 sentence.$delta []  ran
2024-11-03 02:20:02.102013 sentence.$delta []  for
2024-11-03 02:20:02.118886 sentence.$delta []  its
2024-11-03 02:20:02.136612 sentence.$delta []  life
2024-11-03 02:20:02.154099 sentence.$delta [] .
2024-11-03 02:20:02.258635 sentence [] The cat chased the mouse as it ran for its life.
2024-11-03 02:20:02.556008 numbers.[] [0] {'value': 123}
2024-11-03 02:20:02.556662 numbers.[].value [0] 123
2024-11-03 02:20:02.747380 numbers.[] [1] {'value': 456}
2024-11-03 02:20:02.748144 numbers.[].value [1] 456
2024-11-03 02:20:02.938182 numbers.[] [2] {'value': 789}
2024-11-03 02:20:02.938688 numbers.[].value [2] 789
2024-11-03 02:20:03.483925  [] {'words': ['cat', 'mouse', 'run'], 'sentence': 'The cat chased the mouse as it ran for its life.', 'numbers': [{'value': 123}, {'value': 456}, {'value': 789}, {'value': 101112}]}
2024-11-03 02:20:03.484688 numbers [] [{'value': 123}, {'value': 456}, {'value': 789}, {'value': 101112}]
2024-11-03 02:20:03.485579 numbers.[] [3] {'value': 101112}
2024-11-03 02:20:03.486465 numbers.[].value [3] 101112

最终Result:
2024-11-03 02:20:03.490869 {'words': ['cat', 'mouse', 'run'], 'sentence': 'The cat chased the mouse as it ran for its life.', 'numbers': [{'value': 123}, {'value': 456}, {'value': 789}, {'value': 101112}]}

实战案例


Capital of Statistics

PerfXLab

加入社群


  • 加入微信讨论群


    点击这里或扫描下方二维码申请入群

  • 加入Discord讨论群


    点击这里或扫描下方二维码直接加入