乐于分享
好东西不私藏

大模型时代,我们需要一种新的软件范式:声明式文本工程

大模型时代,我们需要一种新的软件范式:声明式文本工程

当业务逻辑变成“文本→结构化数据”,if/else 就不再是工具,而是债务


一句话概览

最近在做一些开发项目的时候,越来越觉得现在的软件开发不够AI NAIVE,就想着构思一个框架:接收自然语言,按照你定义的规则,输出可被下游消费的结构化数据。它不是要替代 Function Call、MCP 或现有组件,而是成为它们前面的“语义理解层”。


一、背景:真实到令人头疼的三个场景

场景一:那个凌晨两点的紧急需求

产品经理发来消息:“用户反馈说,能不能把我们客服聊天记录里的差评自动分类一下?就是那种‘物流慢’、‘质量差’、‘态度不好’……大概分个五六类就行,明天能用上吗?”

你心里清楚:写正则?维度太多。训练分类模型?时间不够。最终你选择了大模型。

第二天你交了代码:一个 Python 脚本,调 OpenAI API,prompt 写在三引号字符串里,输出用正则硬拆。能用,但你知道这是一颗定时炸弹。

一个月后,分类维度变成 12 类,prompt 被改了 20 多次,那段正则已经没人敢动了。每次改一个词都要重新测全量样本。组里新来的同事问:“这段逻辑为什么要这么写?”你沉默了几秒,说:“因为当时只有两天。”

场景二:那个被 if/else 淹没的“智能客服”

你们做了一个 AI 客服,用户可以问各种问题:“订单到哪了?”“我要退货”“你们公司几点下班”“帮我查一下积分”“机器人你好可爱”……

你用了大模型做意图识别。最初 5 个意图,代码很优雅。后来变成 12 个。再后来变成 30 个。现在的代码长这样:

if "订单" in text or "物流" in text or "快递" in text:
    if "在哪" in text or "进度" in text:
        return intent_order_tracking
    elif "退货" in text or "退款" in text:
        return intent_return
...

这段代码已经改不动了。不是因为逻辑复杂,而是因为没有人能确定改一行会不会影响另一个意图。

你想把 prompt 抽出来做成配置,但 prompt 里有很多 case,互相依赖,抽出来反而更乱。

场景三:那个永远对不上的“输出格式”

你接了一个需求:从用户评价里提取“产品名”、“评价维度”、“情感倾向”,然后传给一个 Dashboard 组件展示。

大模型每次输出都不一样。有时候输出 JSON,有时候在 JSON 前后加一句解释。有时候把“情感倾向”写成“sentiment”,有时候写成“emotion”。你加了各种后处理代码:正则提取 JSON、字段映射、默认值填充。代码量比业务逻辑还多。

更崩溃的是,上个月模型升级了,输出风格又变了。你的后处理代码又得改一遍。

你问自己:为什么每次改模型都要改代码?为什么不能定义一个输出契约,让模型严格遵守?


二、这些场景暴露了同一个问题

上面的三个场景,表面问题不同,根因是一样的:

我们在用“面向确定性执行”的编程模型,去应对一个“语义不确定”的世界

传统编程的假设是:

  • • 输入格式是固定的
  • • 输出结构是确定的
  • • 分支逻辑可以穷举

但大模型应用的现实是:

  • • 输入是任意的自然语言
  • • 输出每次可能不一样
  • • 分支无法提前穷举

所以你会看到:

  • • Prompt 散落在代码字符串里 → 改需求要改代码
  • • 路由靠 if/else 堆砌 → 每加一个意图就加一个分支
  • • 输出格式用正则硬修 → 模型一升级就崩

这不是你的代码写得不够好,是范式不匹配。


三、目的:把“文本→结构化”这个环节标准化

我们想做一件事:把“自然语言 → 结构化数据”这个环节,从业务代码里抽离出来,变成一个独立的框架层。

这个框架的核心主张是:

当你的业务逻辑本质上是对“文本”的处理和转换,你应该用声明式的方式定义规则,而不是用 if/else 硬编码。

框架的定位:

  • • 不做:Function Call、MCP、UI 组件、执行层
  • • 只做:接收自然语言,输出结构化契约

四、四个核心概念

1. DocModel:输出契约

定义“我希望输出什么样子的数据”。可以理解为一种轻量本体——某个实物或虚拟概念的属性、能力、关联关系,以 Markdown 或 JSON Schema 为载体。

2. Skill:最小的转换单元

每个 Skill 包含:

  • • name:唯一标识
  • • describe:这个 Skill 做什么
  • • 触发条件:什么情况下该用这个 Skill(必须写清楚,框架不负责猜)
  • • 输出绑定:对应哪个 DocModel

Skill 之间的互斥性由开发者设计时保证,框架提供检测告警。

3. 软路由:匹配与分发

接收用户输入,根据 Skill 的触发条件进行匹配,选择最合适的 Skill,调用大模型执行转换。这是显式规则匹配,不是黑盒。

4. 适配器:对接现有生态

框架输出的是结构化数据(如 JSON)。适配器负责把它转成下游需要的格式:Function Call 参数、MCP 请求、UI 组件的 props 等。


五、完整流转示例:处理个人群聊数据

假设你是一个重度社群用户,每天有几十个群的几千条消息。你想让框架帮你自动处理这些数据。

场景设定

你有几个微信群:

  • • 行业资讯群:每天有人丢链接和文章
  • • 项目协作群:讨论需求和 bug
  • • 闲聊群:各种段子和日常

你想做的事:

  • • 行业资讯群:提取链接 → 自动生成摘要
  • • 项目协作群:识别待办事项 → 生成任务列表
  • • 闲聊群:不需要处理

流转过程

第一步:定义 DocModel

定义两个输出契约:

  • • ArticleSummary:标题、来源、核心观点、链接
  • • TaskItem:任务描述、负责人(如果提到)、截止时间(如果提到)

第二步:注册 Skill

注册两个 Skill:

  • • extract_links:触发条件包含“链接”、“文章”、“分享”等,输出绑定 ArticleSummary
  • • extract_todo:触发条件包含“待办”、“需要”、“麻烦谁”等,输出绑定 TaskItem

第三步:软路由处理

群聊消息流入框架。软路由逐条匹配:

  • • “有人分享了一篇关于 RAG 的文章” → 匹配 extract_links
  • • “@张三 需要在下周前完成方案” → 匹配 extract_todo
  • • “今天天气不错” → 无匹配,静默丢弃

第四步:适配器输出

匹配到的消息:

  • • extract_links 的输出通过适配器 → 存入“待读列表”或推送到笔记工具
  • • extract_todo 的输出通过适配器 → 同步到项目管理工具(如 Notion、Trello)

这个例子说明了什么?

  • • 框架处理的是大量松散文本 → 高密度结构化数据
  • • 开发者只需要定义“什么样的文本对应什么样的输出”
  • • 下游可以接任何现有工具,框架不关心

六、与现有生态的关系

现有生态
本框架的角色
Function Call
框架负责把自然语言转成入参
MCP Server
框架负责把意图转成 MCP 请求
UI 组件
框架负责把数据格式化成组件可读的 props
Dify / LangChain
可以互补,不是替代

一句话:框架是执行层前面的语义理解层。


七、边界:不是什么?

这个框架不适合:

  • • 毫秒级实时响应
  • • 纯数值计算
  • • 确定性逻辑(直接写 if/else 就好)

它适合:

  • • 非结构化文本 → 结构化数据
  • • 多源文档 → 统一格式
  • • 自然语言意图 → 精确参数提取

八、当前状态与讨论邀请

目前这是一个概念构思,还没有代码实现。

核心待讨论的问题:

  • • Skill 的互斥设计是否可行?
  • • 适配器的抽象层级是否合理?
  • • 是否有同类项目已经在做类似的事?

如果你也在思考大模型应用的工程化问题,欢迎留言或私信讨论。

现在需要的是反馈,不是赞美。


九、最后

如果你有建议,或者觉得某个概念不合理,欢迎大家的讨论。


相关学习资料