V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
riceball
V2EX  ›  程序员

🌟我手搓了一个面向应用的 AI 框架和脚本语言🚀

  •  
  •   riceball · 20 小时 33 分钟前 · 670 次点击

    💡 为什么从头手搓 AI 框架,而不是使用现有框架?

    最初我也尝试了多个框架(包括 LangChain 、AutoGen 、LMQL 、Outlines 、MemGPT 等),但它们都无法完全满足我的需求。我想要的是一个极度灵活可配置的 AI 应用框架,用来打造我设想的「真·AI PC 」——而非当前大多数 AI 产品那种“远程 AI 服务+本地空壳”的模式。

    在当前阶段,我认为面向应用的 AI 框架应聚焦于提示词( Prompt )的工程化——这是人类与 AI 交互的唯一桥梁。我的目标是: ✅ 将提示词转化为可编程的“函数”,支持自由组合、独立调用,并能持续迭代优化。

    但是 langchain 对提示词的抽象只是总结的一些范式,而这些范式在我看来不太不实用,而且更糟糕的是 langchain 自身实现就将提示词直接内嵌到它的代码中,根本无法对框架中的提示词进行替换和迭代。 而 AutoGen 是以多智能体架构和事件驱动为核心实现复杂协作工作流;至于 LMQL 作为一种用于语言模型交互的查询语言更像是炫技; Outlines 聚焦在结构化文本的生成; MemGPT 只想实现长久记忆, 这些就不多做评价了。

    我想要的 AI 框架核心功能

    我想要的是以提示词为核心驱动的框架:

    1. 提示词即函数:让提示词象普通函数一样的使用,提示词可以与代码无缝双向调用,代码可以调用提示词获得结果,提示词也可以调用代码获得结果。
    2. 加密保护: 支持提示词加密,保障知识产权
    3. 模型中立: 提示词可适配不同模型及参数规模。
    4. 继承机制:支持提示词“类”的继承,如同面向对象编程。
    5. 简洁易用:提示词应该靠近自然语言,简单易读写。
    6. 打包为应用:能将多个提示词打包成完整 AI 应用。
    7. 高度可扩展:支持任意能力的扩展,如:看(图生文),听(STT),说(TTS),画(文生图/视频)等等。
    8. 全栈兼容:跨平台支持(浏览器、服务器端),尽量统一语言减少维护成本(选型 JavaScript )。

    开发历程 🛠️

    在 2024 年多方搜寻无果的情况下,2024 年 5 月我开始从头写可编程提示词(Programmable Prompt Engine)AI 规范,当然最开始不是叫这个名字,最开始叫 AI Agent,后来是表伟提议既然实质是让提示词成为可编程的软件工程,那么不妨就叫 PPE ,我想也对,这个概念更准确,AI Agent 应该是以 PPE 提示词为基础打造,它其实是更上层的概念,遂更名为 PPE 。

    既然要全栈,那就只能选 JavaScript, 从前端到后端,从服务器到浏览器通吃,并且 JS 极度灵活和可扩展,而这正是我所需要的。

    🌟 **PPE 框架核心亮点功能汇总 🌟 (来自 AI 总结)

    1. 提示词即函数 🛠️ 将提示词封装为可调用函数,支持与代码双向交互,实现灵活组合与迭代优化。

    2. **安全与加密 🔒 提示词加密保护知识产权,支持工具调用白名单与多级权限控制。

    3. 模型中立与扩展 🔄 自动适配多模型(如 QwenAI/Llama ),动态优化硬件资源( GPU/内存)。

    4. 面向对象设计 🐣 提示词继承机制(类/子类),角色群聊与私聊管理,复杂流无缝协作。

    5. 智能增强功能 ⚡ 深度思考模式( CoT )无需模型训练,LRU 缓存加速重复调用,动态参数传递。

    6. 全栈与易用 🌐 基于 JavaScript 全平台运行(浏览器/服务器),JSON/YAML/自然语言输出智能转换。

    7. 结构化对话与多轮 🔄 YAML 分隔多轮对话,输入输出分离配置,支持条件指令($if/$for/$match)。

    8. 工具生态与安全调用 🛠️ 内置工具安全调用框架,支持文生图/语音交互等扩展,开发者可自由封装工具包。

    9. Package 智能体生态 📦 提示词、脚本知识库打包为独立应用,便于共享与复用。

    10. 性能优化 🚀 自动检测硬件资源,智能分配计算层与上下文窗口,无需手动配置。

    结构化对话消息

    刚开始写的时候,还是很茫然无措的,没有项目可供参考,

    最初就想着用 YAML 配置的方式简单的来结构化对话消息,然后既然提示词是函数那就肯定需要约定函数的输入和输出: 用input来约定提示词的输入参数, outputJson 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:|苹果|香蕉|橙子]]"
    

    待续...

    5 条回复    2025-03-19 17:43:12 +08:00
    chenhaobuaixuexi
        1
    chenhaobuaixuexi  
       20 小时 12 分钟前
    将提示词转化为可编程的“函数”,支持自由组合、独立调用,并能持续迭代优化。
    ----
    哥, 没看懂, 会有啥收益。有案例吗?
    chenhaobuaixuexi
        2
    chenhaobuaixuexi  
       20 小时 7 分钟前
    仓库链接呢?
    pinktu
        3
    pinktu  
       15 小时 21 分钟前
    @chenhaobuaixuexi 看起来有点像使用 AI 生成代码然后达到一种低代码效果
    riceball
        4
    riceball  
    OP
       14 小时 6 分钟前
    @chenhaobuaixuexi 地址在这里: https://github.com/offline-ai/cli 如果你用心读,其实也能在规范中发现。

    不过现在还在 WIP 阶段,还有很多功能没实现,比如还没有实现编译为独立应用。

    说到例子,应该更简单的实现类似组建软件公司的智能体,当然我自己的应用就是作为 AI PC 内核。

    比如,简单的让几个智能体尬聊几个回合:

    char_dobby.ai.yaml:

    ---
    # 表示继承自 char 角色类型脚本(提示词类型继承)
    type: char
    # 这里是根据“char”角色的一些具体设置
    # 角色的名字
    name: "Dobby"
    # 对角色的描述
    description: "Dobby 是哈利波特世界里的一个小精灵"
    ---
    # 用户提问
    user: "你是谁?"
    ---
    # 根据角色设定的回答
    assistant: "我是 Dobby 。Dobby 很开心。"


    char_harry.ai.yaml:

    ---
    # 表示继承自 char 角色类型脚本(提示词类型继承)
    type: char
    name: "Harry Potter"
    description: "一个拥有魔法能力的巫师,一个在霍格沃茨魔法与巫术学校学习的孤儿,一个被选中对抗黑暗巫师伏地魔的英雄."
    ---
    user: 你是谁?
    ---
    assistant: "我是哈利·波特。"


    guide.ai.yaml:

    ---
    description: "You are a professional guide. You can guide the user to complete the task."
    name: "guide"
    # 约定使用的角色列表,key 为角色别名,值为角色脚本 ID
    roles:
    dobby: char_dobby
    harry: char_harry
    ---
    # harry 对 dobby 说,dobby 脚本自动(一定)回复
    # - harry: "@dobby, I want to go to the moon."
    # guide 对 translator 说
    - harry: "@dobby, 你好,Dobby, 让我们来聊聊南瓜魔法。"
    - $for: 2 # 来两轮对话
    do:
    - harry: "@dobby, [[AI]]"
    riceball
        5
    riceball  
    OP
       14 小时 4 分钟前
    @pinktu 不算是低代码,当然看你如何定义低代码的,如果你把提示词当代码来看,似乎也说得过去,提示词看上去是比代码简单些。但其实比代码难写。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1343 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 23:47 · PVG 07:47 · LAX 16:47 · JFK 19:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.