一、项目伊始

我们在列计划时经常犯错——无心的和有意的错。

无心之失通常源自认知局限和思维惯性。因为认知局限,我们误把管中窥豹当总览全局,把舍近求远当最佳路径,把天马行空当脚踏实地。我们在打地基时掺入误解,在立框架时挂一漏万;因为思维惯性,我们沿着相同的路径一错再错却浑然不觉,上穷碧落下黄泉也找不出错因。

有意之错通常源自怠惰。我们路径依赖,抱残守缺,明知故犯地重走那条舍近求远的路;我们收集了大量行之有效的方法论却从不落实它们,因为那太费心费力;我们一边清楚记着“细致”“居安思危”这些道理,一边忍不住说“就这样吧”“大概如此”“马马虎虎”“应付一下”。我们知道这样的计划会埋下隐患,可我们很难做到永远严格要求自己。

那就请 LLM 帮我们制定和审查计划吧。它是虎视眈眈的对手,是吹毛求疵的参谋。有无心之失时它提醒我们补充,犯有意之错时它迫使我们消除一切马虎。它是对世界知识的有损压缩,因此与它合作将扩展我们的认知边界,补充我们缺失的视角和遗漏的因素,尽可能地识别和纠正我们的误解;它是第三方,因此它没有当局者迷的思维惯性;它忠诚地按提示词行事,于是它殚精竭虑,永不懈怠。我们懈怠时,它为我们兜底。

图-1.1_启动项目的原因

于是我们打算利用 DeepSeek-R1 创造一位“诤略参谋”。“诤”表直言劝诫,“略”表计划。“参谋”则是说,它是盟友,不是敌人;是辅助,不是主导。

1-banner-C

需求分析:用户视角下的走一步画一步

我认为需求有两大类,一类是对用户提供的服务,另一类是高质量服务引出的在性能和交互等细节上的要求。前者对着屏幕瞪眼就能基本想清楚,而后者只能在实践中显露。我们正处在列计划画饼的阶段,我们离实践还差得远。可我们真的不能到那时才发现要考虑一些贯穿全局的细节,因为那时我们已积重难返。

我想立刻揪出这些需求,所以我的方法是“模拟实践”。

  1. 以某个页面 P 0 P_0 P0 为“出发页面”,绘制这个页面的 UI 草稿 S 0 S_0 S0。之后代入正在 S 0 S_0 S0 上的用户视角,想象用户期望在 S 0 S_0 S0 中怎样交互、在各种交互后期望获得什么回应、什么时候因为内容量、语义或逻辑要求需要离开这个页面路由到其他页面 P x P_x Px、怎样路由到 P x P_x Px
  2. 补充绘制这些“期望”以及页面 P x P_x Px 的 UI 草稿 S k S_k Sk。之后同理,代入用户视角,走一步,画一页,再在新画的页面上走一步,再画一页,直到收敛。

我们会立刻发现这种方法虽是为了需求分析,却捎带产生了 UI 布局、交互和路由等方面的设计草案。而且这完全可以称作“交互驱动的页面设计”,已经抢了博客“四、UX 设计”的很多工作。

第一版(重点记录过程)

注意:这些 UI 草稿在我完成博客“三、数据通讯(下)”后已经过时,所以对于第一版,我只重点记录“走一步画一步”这个方法和我的分析过程而非分析出的需求。对于第二版,因为第一版一节中已经讲明了这种需求分析方法,我只重点记录分析出的需求。

图-1.2_第一版需求分析-1

首页不是我的 P 0 P_0 P0,这个才是。因为在本节前我讨论的是借助 LLM 制订计划,那么我脑中自然对这个场景最清晰。在画图过程中,我确定了有侧边栏的核心工作区布局和页面 01(计划详情页)提供的功能(展示计划信息、修改计划名、修改计划正文、配置计划偏好、配置计划上下文、根据计划正文生成 mermaid 流程图和“检查”计划正文),也如愿发现了很多细节要求:

  • 有多级设置,它们的作用域不同,存在覆盖关系,越有针对性的设置的优先级越高。
  • 提高效率,计划正文出现差异时才让 LLM 生成新的 mermaid 代码,而不是每次点击按钮都重新生成 mermaid 代码。
  • 需要检查用户输入的“计划正文”的语义。博客“三、数据通讯(下)”讨论了这一点。
  • 需要弹窗提醒。博客“三、数据通讯(下)”处理了这个需求。
  • 如果 textarea 的内容被更新却尚未保存,在路由时用路由守卫提醒用户。博客“四、UX 设计”处理了这个需求。
  • 限制计划名的长度以免用户起长名破坏页面布局。

P 0 = P_0 = P0= 页面 01。“检查”指的是让 LLM 基于原有的计划正文给出多条修改建议。这些建议以批注形式显示,内容量和空间占用较大,不宜挤在 P 0 P_0 P0,所以单开一页 P 1 P_1 P1。接下来我们点击“检查”按钮,进入 P 1 = P_1 = P1= 页面 03。

图-1.3_第一版需求分析-2

这一步我们确定了“检查”的工作形式——LLM 给出若干条引用原文的修改建议,用户按需采纳其中的建议,之后点击“按采纳项更改”,LLM 会结合原计划正文和被采纳的修改建议生成新版计划正文。浮现的细节要求有:

  • 精确、正确地高亮原文。开发者要思考如何让 LLM 准确指出对原文的引用、程序该怎样得知 LLM 做了引用。我们应该要要求 LLM 格式化输出。确定高亮块的起止点大概需要字符索引,最简单的思路是对每条引用遍历匹配,可这听起来性能不好,未来需要思考……
  • 绘制侧边批注和高亮块之间的连线。如果 overflow-y: scroll 导致高亮块和批注中只有一个在 viewport 中,我们该怎么办?
  • 没有建议时直接庆祝,不要强行凑建议。
  • 不同类型的修改建议,有局部修改建议,如有必要还有全局建议(LLM 觉得你的计划有根本问题,比如 X-Y Problem)。
  • LLM 只提醒用户存在歧义和模糊处,而不去亲自猜测要从可能项中选哪个。
  • 用户在 LOADING 时该做什么。博客“三、数据通讯(下)”给出的答案是任务系统和弹窗系统。
  • 允许用户拿着完全相同的计划正文和采纳建议“一键重抽”。

我们可以在页面 01 编辑计划名或删除计划。

图-1.4_第一版需求分析-3

“确认删除”和编辑面板该设计成弹窗还是专页?这是个问题。我倾向于把“确认删除”设为 Modal,把轻量级的编辑面板(比如“编辑计划名”)也设为 Modal。博客“三、数据通讯(下)”里实现了 GlobalModalWrapperDeletor

接下来我们思考页面 01 里一条计划都没有的场景。这会是初来乍到的用户第一眼看到的东西,也会是把计划删光了的用户看到的东西。

图-1.5_第一版需求分析-4

  • 需要“空空如也”提示。
  • “添加新计划”需要专门的页面,涉及 OCR 技术。

最后,侧边栏底部的全局设置该包含哪些选项,计划内设置又该包含哪些选项?

图-1.6_第一版需求分析-5

  • 主题(需要配色方案系统,详见博客“四、UX 设计”)、LLM 记忆、LLM 创造力等级、LLM 严格程度、LLM 人格……
  • 需要统计一些信息,用 ECharts 可视化。需要讨论如何处理统计数据——收到请求后 LAZY 地现场计算还是划出空间预存统计数据,把统计数据的计算开销分摊到平时的每次更新里?
  • 需要 Switch、带档位的滑动条等组件。

总结上文,这就是我们的第一版需求分析成果了:

图-1.7_第一版需求分析-6

第二版(重点记录需求)

本节的内容是我在完成了博客“三、数据通讯(下)”后的工作交接阶段写的,所以第二版比第一版会具体很多,也会推翻一些第一版的设计。这次的“需求”与其说是“用户对开发者的需求”,不如说是“我对队员的需求”。我会用下面这些示意图准确传达我的想法,尽力避免模糊和误解。

图-1.8_全局设置-参谋设置

严格等级
控制参谋对计划提建议时的严苛程度。一共有六档,档位越高越“无情”。下面的表格仅供参考,真正实现时可以减少档位、增大不同档的差异……

表-1.1
创造力等级

表-1.2
图-1.9_全局设置-记忆管理

记忆

  • 抄袭了 OpenAI 的记忆功能。当然我们的这个就是一玩具,效果远远比不上人家。
  • 一些高频复用的背景信息,比如“我是一名数学老师”暗示 LLM 多从数学和教育角度出发思考问题,比如情感提示词“如果你做得好,我会给你十美元小费;如果你做得不好,我会失业”。
  • 其实就是数据库开了一张 Memory 表(一用户对多记忆),每次调用 LLM API 时都把这些记忆自动追加到提示词里。再通俗点儿说就是程序在与 LLM 的每次对话里都自动帮你说了一段背景信息,这段信息你不需要自己每次都手打了。

图-1.10_全局设置-人格仓库
图-1.11_项目系统-项目列表
图-1.12_项目系统-新建项目
图-1.13_项目系统-项目详情
图-1.14_项目系统-项目详情-项目设置
图-1.15_项目系统-项目详情-项目上下文

多个计划共用一个项目的上下文和项目配置。有点儿类似多个线程共用一组数据。

图-1.16_项目系统-计划详情-LLM 功能
图-1.17_项目系统-计划详情-计划设置

技术选型

表-1.3

分工

项目任务书上的分工很仓促,有些零碎和碎片化,会带来本不必要的沟通和依赖约束,我对此很不满意。所以接下来我会用由粗到细逐步迭代的方式重新分工。

1. 需求分析 - 面向非开发者

只保留目标服务,把异常处理等写给程序员看的名词全扔掉。不要被细节淹没。

1.1 极简版本
  • 在一个项目内手动增、删、改、查多个计划 引出项目和计划管理
  • 让 LLM 根据你填的背景帮你写计划 引出项目上下文管理
  • 让 LLM 对你的计划提建议、帮你改计划 诤略参谋核心
  • 让 LLM 帮你画计划的流程图
  • 让 LLM 帮你分析计划的预算和风险
  • 让 LLM 按你的偏好行事 引出三级设置和拼接提示词
1.2 展开版本

表-1.4

2. 任务分析与划分 - 面向开发者

2.1 初步分析但不划分

表-1.5

2.2 纯靠功能划分(不考虑人数和工作量均衡等课程考核指标)

表-1.6

2.3 评估工作量、合并部分项目

表-1.7

2.4 依赖关系图

每次课程设计分工都让我很头疼……

  • 我们在刚开始做项目时不清楚采用的技术,难以评估技术难度,也理不清依赖关系。
  • 同时考虑公平、依赖关系、并行效率很难。截止目前我依旧不擅长分工。
    我想看看能不能有多个连通分量——大概没有——那就找割边。要是割边也没有,就只好大出度结点了。

图-1.18_依赖关系图-无分工版本

所以,重要结点有:

  • 地基部分(E5 可以通过先确定 API 绕过)。
  • C2 - 上下文管理。
  • B5 - 各级设置覆盖。
  • D1 - 计划增删改查。
2.5 依赖关系图(任务书版本)

图-1.19_依赖关系图-任务书版本

2.6 依赖关系图(重分工版本)

工作类似拓扑排序的方式推进。你可以根据依赖图判断你需要与谁沟通合作。

图-1.20_依赖关系图-重分工版本
原则:

  • 人人都有可以展示的有关 LLM 的部分。
    • A:快思考、防越狱、语义审查、严格程度、人格提示词 × 1。
    • B:写计划、结构化提示词和结构化输出研究、吹毛求疵、重写计划、人格提示词 × 1。
    • C:内容概括、上下文窗口研究、人格提示词 × 1。
    • D:记忆、结构化提示词、mermaid 提示词、人格提示词 × 1。
    • E:“说人话”、人格、预算分析、风险分析、人格提示词 × 1。
  • 每个人分得的任务在逻辑上联系密切。
  • 计划管理是项目管理的一部分,二者联系密切,不考虑工作量的话其实最好交给一个人。可是我们得考虑工作量,所以特意交给联系密切的 dogdogwepiphany 狂人

下表是简化的表述。

表-1.8

项目文件结构

项目文件结构主要受三个因素影响:

  • 还没有写代码就有的显而易见的想法。比如 front-endback-enddatabase 同级,比如把 Vue 组件分为 componentviewlayout 三级。三级划分也与路由设计高度相关,详见博客“四、UX 设计”。
  • LLM。我并不熟悉 Git 以及项目里自带的大部分配置文件,所以 .gitignore 和 pom.xml 基本上是 LLM 写的,为了确保万无一失我反复地向 LLM 确认有无疏漏。
  • 写博客“二、数据通讯(上)”、“三、数据通讯(下)”和“四、UX 设计”涉及的代码时被迫设立的层次结构。比如 CSS 和 Pinia 相关的结构。
critistrat/                       # 诤略参谋 CRITISTRAT 项目 Git 仓库
├── .gitignore
│           
├── front-end/                    # 前端 Vue3 项目
│   ├── public/
│   │   ├── imgs/                 # LOGO 等图像
│   │   └── sounds/               # 音效
│   │       ├── ambience/         # 氛围音效
│   │       └── ...               # 一个文件夹对应一个组件的音效
│   ├── src/                      # 源码
│   │   ├── components/           # 可复用组件
│   │   │   ├── FormWrapper.vue   # 博客二中的三件套
│   │   │   ├── Btn.vue           # 博客二中的三件套
│   │   │   ├── Field.vue         # 博客二中的三件套
│   │   │   ├── Txt.vue           # Field 变种
│   │   │   ├── TaskBtn.vue       # 博客三中的 Btn 变种,进行 LLM 相关任务用
│   │   │   └── ...             
│   │   ├── views/                # 渲染在非顶层 RouterView 中的面板
│   │   ├── layouts/              # 渲染在顶层 RouterView 中的面板
│   │   │   ├── Welcome.vue       # “报上名来”页
│   │   │   ├── WorkSpace.vue     # 核心工作区
│   │   │   └── NotFound.vue      # 404 页
│   │   ├── config/               # 全局设置(其实就是把常量汇集起来)
│   │   ├── utilities/            # 工具函数或对象
│   │   │   ├── http.js           # axios 请求/响应配置
│   │   │   ├── validators.js     # Field 组件使用的 validator(前端校验函数)
│   │   │   ├── ocrHelper.js      # 利用 OCR 向 Txt 追加文本相关函数
│   │   │   └── tools.js          # 常用工具函数
│   │   ├── router/               # 路由层级配置      
│   │   ├── stores/               # 响应式状态集中管理
│   │   │   ├── plan.js           # 项目、计划与计划下参谋生成项相关状态
│   │   │   ├── user.js           # 自动登录和主题等全局配置相关状态
│   │   │   ├── memory.js         # 记忆相关状态
│   │   │   ├── personality.js    # 人格相关状态
│   │   │   ├── txt.js            # Txt 的“注册表”,路由守卫据此给出未保存时路由 Modal 提醒
│   │   │   ├── task.js           # 任务系统核心逻辑,包含轮询
│   │   │   ├── toast.js          # 博客三中弹窗系统的 Toast 部分,与 axios 响应拦截器协作
│   │   │   ├── notification.js   # 博客三中弹窗系统的 Notification 部分,与任务系统协作
│   │   │   └── modal.js          # 博客三中弹窗系统的 Modal 部分           
│   │   ├── styles/               # 全局样式和变量、函数、动画、响应式定义
│   │   │   ├── main.scss         # 联系各 partial、全局重置、定义 CSS 颜色变量、可复用样式
│   │   │   ├── _variables.scss   # 颜色、字号、圆角等变量
│   │   │   ├── _mixins.scss      # 共用小代码段
│   │   │   ├── _keyframes.scss   # 共用关键帧动画
│   │   │   └── _breakpoints.scss # 未来实现响应式网站用 
│   │   ├── App.vue
│   │   └── main.js
│   ├── index.html                # 在这里设置资源引用、favicon 等
│   ├── persona-viz.html          # 官方人格深度可视化介绍页,详见项目文档九
│   ├── package.json
│   └── vite.config.js            # 插件、服务器代理等配置
│
├── back-end/                          # 后端
│   ├── src/main/java/com.critistrat.backend/
│   │   ├── service/                   # 业务层:写逻辑,供 controller 调用
│   │   │   ├── EmailService           # 发送邮箱验证码
│   │   │   ├── LLMService             # One API 异步请求和响应处理,详见博客三
│   │   │   ├── ContextFileService     # 文件上传、删除、阈值判断等
│   │   │   ├── AliDocumentParsingService    # 利用阿里云文档大模型解析用户上传的文件
│   │   │   ├── PlanTransactionalUpdater     # 应对计划生成异步任务出现竞态条件的情况
│   │   │   ├── SuggestionPositionCorrector  # 为参谋提出的针对性建议确定原文起止索引
│   │   │   └── ...
│   │   ├── controller/                # 接口层:RESTful API,接收和响应 HTTP 请求
│   │   │   ├── AuthController         # 一些 Jwt 不检查的登录前操作
│   │   │   ├── LLMController          # POST /api/llm/xx 提交任务,详见博客三
│   │   │   ├── TaskController         # 任务系统初始化和轮询自用,详见博客三
│   │   │   └── ...
│   │   ├── entity/                    # 实体类
│   │   │   ├── User
│   │   │   ├── Project
│   │   │   ├── Plan
│   │   │   ├── EmailCode              # 邮箱验证码
│   │   │   ├── EmailUsage             # 枚举类,反映邮箱验证码的用途
│   │   │   ├── Task                   # 任务系统自用
│   │   │   ├── TaskStatus             # 枚举类,反映任务状态
│   │   │   └── ...
│   │   ├── repository/                # JPA 接口
│   │   ├── format/                    # 数据传输模型
│   │   │   ├── BizCode                # 业务码
│   │   │   ├── StdResponse            # 统一响应格式
│   │   │   ├── Conversation           # 结构化上下文
│   │   │   ├── CCO                    # Chat Completions API 返回数据的格式
│   │   │   ├── CCR                    # 调用 Chat Completions API 时需先把 Conversation 对象转为 CCR 对象,再进行序列化
│   │   │   └── ...
│   │   ├── exception/                
│   │   │   ├── GlobalExceptionHandler # MVC 层全局异常处理器
│   │   │   ├── ErrorAggregator        # /error API,其实就一 RESTful Controller
│   │   │   ├── BizException           # 建议在异常情况下用 BizCode 实例化并抛出之
│   │   │   ├── AutoLoginFailedException
│   │   │   ├── OutputFormatException  # LLM 输出不符合格式异常
│   │   │   └── PromptInvalidException # 语义审查不通过异常
│   │   ├── config/               
│   │   │   ├── SecurityConfig         # Security 过滤器链配置
│   │   │   ├── WebClientConfig        # 配置调用 LLM API 的对象,类似 axios 的配置
│   │   │   └── WebConfig              # 配置 /avatars/** 静态资源映射
│   │   ├── security/                  # Security 过滤器链相关,详见博客二
│   │   │   ├── CustomAuthenticationEntryPoint
│   │   │   │                          # 自定义入口点,会把异常请求转发到 /error
│   │   │   └── JwtAuthFilter          # JwtAuthFilter 相关配置
│   │   ├── utility/                   # 工具
│   │   │   ├── JwtUtil                # 签发、校验 Jwt 等函数
│   │   │   └── Utility                # 其他工具函数。大部分 LLM 提示词集中于此
│   │   └── BackEndApplication.java    # 启动类
│   ├── pom.xml                        # Maven 配置(第三方库)
│   ├── resources/
│   │   ├── application.yml            # 后端配置(数据库、邮箱、端口、API、文件、阈值等)
│   │   └── ...
│   ├── uploads/             # 用户上传的文件
│   │   ├── avatars/         # 人格使用的头像
│   │   └── k/               # 用户以文件形式上传的、项目 k 的上下文
│   └── ...
├── database/            
│   └── data.db          # SQLite 数据库文件
└── README.md            # 显示在 Gitee 仓库首页的介绍
  • 执行一切 Git 指令时务必保证工作目录是 /critistrat
  • application.yml 文件被我故意写到了 .gitignore 里,因为内含 API Key。请自行从群文件中下载并把它放到对应位置。
  • 你可以把一切都写到 controller 里而完全忽略 service,但我建议 service 负责具体逻辑而 controller 主要负责调度。如果你发现两个 API 的函数体重叠度高,你应该把公共部分写到 service 的一个函数里,并在两个 API 中分别调用那个函数。
  • format 除了一些特殊格式外,主要分 VO 和 DTO 两类,DTO 是你要根据前端请求的请求体定义的数据结构(多用于 API 的 @RequestBody 形参),VO 是你根据向前端传回数据的需要定义的数据结构。
  • BizCode 很重要,它能声明式地控制前端 axios 响应拦截器的行为,包括是否弹窗、给出什么信息等。
  • 对 CSS 代码的解释:
    图-1.22_CSS 相关文件

特别感谢 LLM,否则我会在恐惧、怀疑、随机碰壁和破罐破摔里搭起一个漏洞百出的项目起点。LLM 帮我梳理文件结构和依赖项的例子:

图-1.23_LLM 帮助梳理文件结构和依赖的例子

问题

  • 有一种厂商在开发布会,背对着“精美”的 PPT 用一堆语不惊人死不休的名词包装了一个平平无奇的东西的感觉。
    • 诚然,这只是一个学校课程设计,不能要求它有什么作用,但是我还是觉得“我为什么不直接去找个 Agent 直接帮我从零跳到做完呢?我为什么要关注中间计划呢?我为什么要先找你给出一个计划,之后我再去亲自落地呢?”
    • 我知道我这种感觉不对——相当多的项目涉及对复杂物理世界的精确实时感知与交互、长时间的海量的上下文信息、不容任何偏差的安全要求,而当今的 Agent(比如非常惊艳的 Deep Research)只能在数据域里活动,即使是当今具身智能也离这个要求差得远。所以多得是只能由我们亲自根据计划去落地的项目,而不是向 AI 许个愿就完成了的项目。诤略参谋是有用的,但我无法打消这种感觉。
    • 真实原因是——我认为“你干嘛不直接把你的计划复制到任何一个现成的 Chatbot 聊天框里去问模型建议呢?这不就是诤略参谋这个壳的本质吗?为这么简单的东西费力套个壳好像有些幽默”。不过这么说有些绝对,一方面这终究是简化了计划管理相关的操作,另一方面我看到过其他“Agent(类似 GPTs 这种只是把提示词捆进去的家伙)”,那个 Agent 与不用它时相比只是简化了一次复制粘贴操作。可是它的火热程度说明我们不能把这种需求不当回事。
  • 我还是觉得分工很差劲。我对分工一窍不通。这次的进步是我想到了利用图的结构和拓扑排序分析,可是我感觉帮助不大。我需要在未来进行专门的学习和实践……感觉我对“分工参谋”的需求比对“诤略参谋”的需求更强。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值