跳转至

以下内容基本上是 AI 生成的,我还没校对,可能质量不高

me

Reasonify: “我的母语是 Python”

Repo   ·   Home

Reasonify 是一个基于 Promplate 构建的智能 Agent,它的口号是 "Real AI speaks programming language"。

Features

  • Code as Thought: 强迫 AI 用代码(Python/JSON)来表达思考过程,而不是自然语言。
  • Headless Core: 核心逻辑封装为 reasonify-headless 包,可脱离 UI 独立运行。
  • Structured Output: 保证输出的结构化和可执行性。

Implementation

项目分为两部分:

  1. Headless Core: 纯 Python 实现的 Agent 逻辑,定义了 Prompt 模板和状态机。
  2. Web UI: 基于 SvelteKit 构建的界面,通过 Pyodide 在浏览器中直接运行 Core。

主循环架构

得益于 promplate 的设计,定义了每个结点的行为之后,主循环非常简洁:

main_loop = Chain(intro, loop := Loop(main := Node(main))) #(1)!
  1. core/loop.py 定义了 intro -> Loop(main) 的执行链
节点 职责
intro 接收用户输入,注入 reply() / end_of_turn() 工具
main 解析 LLM 输出的 JSON 代码块,调度执行
loop 重复执行直到 end_of_turn(),收集执行结果写入对话

LLM 响应必须是 JSON 数组(代码块列表),每个元素作为独立执行单元。

工具系统

在这个框架下,工具就是函数。其签名就是函数签名,不需要什么 json schema 的复杂表示。LLM 天生懂 python,不用多说:

def tool[T: Callable](function: T) -> T: #(1)!
    get_context()[function.__name__] = function

    prefix = "async def" if isasyncgenfunction(function) or iscoroutinefunction(function) else "def"

    stubs[function.__name__] = f'{prefix} {function.__name__}{Signature.from_callable(function, eval_str=True)}:\n    """{function.__doc__}"""'

    return function
  1. utils/tool.py - @tool 装饰器,将函数注册为工具

然后 tools/*.py 中的每个函数装饰 @tool 后,对 LLM 可见为 Python 函数。

def register_all():
    for file in Path(__file__).parent.glob("*.py"):
        if file.stem != "__init__":
            import_module(f".{file.stem}", __package__) #(1)!
  1. tools/__init__.py 动态导入所有工具注册模块

代码执行

async def run(source: str) -> Result: #(1)!
    context = get_context()
    with redirect_stdout(io), redirect_stderr(io):
        result = await eval_code_async(source, context, filename=filename) #(2)!

    if diff := diff_context(original_context, context):
        out["global values"] = diff
    if logs := io.getvalue():
        out["stdout/stderr"] = logs
    if result is not None:
        out["return"] = result
    return loads(json(out))
  1. utils/run.py - run() 函数执行 LLM 生成的代码块
  2. 这里的 eval_code_async() 来自 pyodide;其实和 IPython 的实现是一样的。这里有个 standalone 的实现:coderunner.py

执行结果通过 system > 消息注入对话上下文,供 LLM 读取后决定下一步。

Few-Shot 示例

示例存储为 YAML,格式为 交互列表,每项是用户消息或 [source, result] 对:

- Who are you? #(1)!
- - source: |
      reply("I am `Reasonify`, the first PythonAgent in the world.")
      end_of_turn()
  1. examples/simple_ask.yaml source 是 Python 代码块,resultget_examples() 执行时动态填充

get_examples() 执行时动态填充 result 字段,确保示例展示真实输出。

巧思

Reasonify 的核心假设是:编程语言是比 JSON 更好的 function_call 方式

通过设计特殊的 System Prompt,我引导 LLM 将"推理"过程转化为"编写代码"的过程。比如,当它需要计算或处理数据时,它不是"说"出结果,而是"写"一段 Python 代码来计算结果。

这种 Reasoning via Coding 的方法显著提高了复杂任务的准确率。

深入洞见

Reasonify 展示了 Isomorphic AI Architecture(同构 AI 架构)。

由于使用了 promplatepyodide 技术栈,Reasonify 的核心 Agent 逻辑是一套 Python 代码,它既可以部署在服务器上作为 API 服务,也可以直接加载到用户的浏览器中运行。

src/routes 中,你可以看到前端如何加载 reasonify-headless,并在本地 Worker 中执行 Agent 逻辑。这种架构极大地降低了服务端的计算压力,同时保护了用户的隐私(数据不出浏览器)。

相关项目

  • Promplate: 构建此 Agent 的基石。
  • Promplate Pyodide: 使 promplate 在 pyodide 环境运行的一个 patch 其能在浏览器运行的关键技术。