riceball:
💡 为什么从头手搓 AI 框架,而不是使用现有框架?
最初我也尝试了多个框架(包括 LangChain 、AutoGen 、LMQL 、Outlines 、MemGPT 等),但它们都无法完全满足我的需求。我想要的是一个极度灵活可配置的 AI 应用框架,用来打造我设想的「真·AI PC 」
——而非当前大多数 AI 产品那种“远程 AI 服务+本地空壳”的模式。
在当前阶段,我认为面向应用的 AI 框架应聚焦于提示词( Prompt )的工程化——这是人类与 AI 交互的唯一桥梁。我的目标是:
✅ 将提示词转化为可编程的“函数”,支持自由组合、独立调用,并能持续迭代优化。
但是 langchain 对提示词的抽象只是总结的一些范式,而这些范式在我看来不太不实用,而且更糟糕的是 langchain 自身实现就将提示词直接内嵌到它的代码中,根本无法对框架中的提示词进行替换和迭代。
而 AutoGen 是以多智能体架构和事件驱动为核心实现复杂协作工作流;至于 LMQL 作为一种用于语言模型交互的查询语言更像是炫技; Outlines 聚焦在结构化文本的生成; MemGPT 只想实现长久记忆, 这些就不多做评价了。
我想要的 AI 框架核心功能
我想要的是以提示词为核心驱动的框架:
- 提示词即函数:让提示词象普通函数一样的使用,提示词可以与代码无缝双向调用,代码可以调用提示词获得结果,提示词也可以调用代码获得结果。
- 加密保护: 支持提示词加密,保障知识产权
- 模型中立: 提示词可适配不同模型及参数规模。
- 继承机制:支持提示词“类”的继承,如同面向对象编程。
- 简洁易用:提示词应该靠近自然语言,简单易读写。
- 打包为应用:能将多个提示词打包成完整 AI 应用。
- 高度可扩展:支持任意能力的扩展,如:看(图生文),听(STT),说(TTS),画(文生图/视频)等等。
- 全栈兼容:跨平台支持(浏览器、服务器端),尽量统一语言减少维护成本(选型 JavaScript )。
开发历程 🛠️
在 2024 年多方搜寻无果的情况下,2024 年 5 月我开始从头写可编程提示词(Programmable Prompt Engine)AI 规范,当然最开始不是叫这个名字,最开始叫 AI Agent,后来是表伟提议既然实质是让提示词成为可编程的软件工程,那么不妨就叫 PPE ,我想也对,这个概念更准确,AI Agent 应该是以 PPE 提示词为基础打造,它其实是更上层的概念,遂更名为 PPE 。
既然要全栈,那就只能选 JavaScript, 从前端到后端,从服务器到浏览器通吃,并且 JS 极度灵活和可扩展,而这正是我所需要的。
🌟 **PPE 框架核心亮点功能汇总 🌟 (来自 AI 总结)
-
提示词即函数
🛠️ 将提示词封装为可调用函数,支持与代码双向交互,实现灵活组合与迭代优化。
-
**安全与加密
🔒 提示词加密保护知识产权,支持工具调用白名单与多级权限控制。
-
模型中立与扩展
🔄 自动适配多模型(如 QwenAI/Llama ),动态优化硬件资源( GPU/内存)。
-
面向对象设计
🐣 提示词继承机制(类/子类),角色群聊与私聊管理,复杂流无缝协作。
-
智能增强功能
⚡ 深度思考模式( CoT )无需模型训练,LRU 缓存加速重复调用,动态参数传递。
-
全栈与易用
🌐 基于 JavaScript 全平台运行(浏览器/服务器),JSON/YAML/自然语言输出智能转换。
-
结构化对话与多轮
🔄 YAML 分隔多轮对话,输入输出分离配置,支持条件指令($if/$for/$match
)。
-
工具生态与安全调用
🛠️ 内置工具安全调用框架,支持文生图/语音交互等扩展,开发者可自由封装工具包。
-
Package 智能体生态
📦 提示词、脚本知识库打包为独立应用,便于共享与复用。
-
性能优化
🚀 自动检测硬件资源,智能分配计算层与上下文窗口,无需手动配置。
结构化对话消息
刚开始写的时候,还是很茫然无措的,没有项目可供参考,
最初就想着用 YAML 配置的方式简单的来结构化对话消息,然后既然提示词是函数那就肯定需要约定函数的输入和输出: 用input
来约定提示词的输入参数, output
用Json Schema
来约定提示词的输出:
templateFormat: hf
prompt:
messages:
- role: system
content: Carefully Think about the intent of following The CONVERSATION user provided. Output the json object with the Intent Category and Reason.
- role: user
content: |-
The CONVERSATION:
{{ conversation }}
input:
conversation: "messages[1].content"
output:
type: object
properties:
Intent:
type: "string"
Reason:
type: "string"
感觉,这样很不自然方便,于是将结构化对话消息的输入/输出配置与对话内容分离:
---
input:
conversation: {required: true}
output:
type: object
properties:
Intent:
type: "string"
Reason:
type: "string"
---
system: Carefully Think about the intent of following The CONVERSATION user provided. Output the json object with the Intent Category and Reason.
user: |-
The CONVERSATION:
{{ conversation }}
这样就感觉好多了。
提示词调用与代码集成
那么如何在提示词中使用(调用)AI 赋值以及其他提示词或代码?于是有了高级替换
:
---
# 导入 js 函数
import:
- eval.js
---
# JOKE 会被 AI 赋值,存放于: `prompt.JOKE` 中,供下次使用
assistant: "讲个笑话:[[JOKE]] 希望您喜欢!"
# 调用外部提示词`calculator`
user: "五加二等于 [[@calculator("5+2")]]"
# 调用函数代码`eval`
user: "五加二等于 [[@$eval("5+2")]]"
// eval.js
export function eval(value) {
return ...
}
甚至支持了让 AI 只能在我给的列表中选择:
user: 你喜欢什么水果?
assistant: "我超喜欢[[FRUIT:|苹果|香蕉|橙子]]"
待续...
Read More