项目实践笔记13:多用户事实碎片 Agent 的接口测试与约束设计

前言:

前面项目一只实现了迭代一,还有迭代二和迭代三,现在先实现迭代二。

项目一在 迭代二阶段 ,从"单人本地脚本"升级为"多用户 + HTTP API + 可回归测试"的过程,重点放在 接口行为约束、模型不可控问题的工程化兜底,以及测试视角的验证方法。

一、做迭代二的原因

在迭代一中,项目已经实现了:

  • 基于 LLM 的事实碎片记录

  • 本地 JSONL 持久化

  • 简单的"查询 / 打卡 / 拒绝"能力

但在使用和测试过程中,会有这些问题:

1、单用户假设不成立

  • 所有碎片默认属于同一个人

  • 无法支持多人同时记录、查询

2、交互不可测试

  • CLI 形式不利于接口回归

  • 无法做系统化测试用例

3、模型行为不稳定

  • 同样的输入,有时 record,有时 reject

  • 低质量输入(如"做了啥")会被错误写入数据

迭代二的目标不是"加功能",而是"让系统可控、可测、可解释"。

2.1 引入 HTTP API(工程入口)

新增:

复制代码
POST /api/input

统一所有行为入口:

  • 记录事实

  • 查询今日碎片

  • 打卡确认

  • 拒绝无效请求

为后续 接口测试 / 自动化 / 回归 打基础。

2.2 引入 author 字段(多用户隔离)

所有请求 author 必填:

复制代码
{
  "text": "今天完成了WMS用例执行",
  "author": "张三"
}

数据层变化:

  • fragments.jsonl 中新增 author

  • 所有查询默认 按 author 过滤

  • 特殊值 author=all 才允许全量查询

这是典型的权限/隔离设计,也是后续测试的重点。

2.3 统一返回 contract(测试关键)

所有 API 响应统一结构:

复制代码
{
  "ok": true,
  "action": "record | query | confirm | reject",
  "tool_called": "record_fragment | get_fragments_by_date | confirm_clock_event | null",
  "today_fragments": [],
  "input_text": "原始输入"
}

设计原则:

  • reject / confirm 必须返回空数组

  • 前端 / 测试代码 不需要猜行为

  • 行为通过 action + tool_called 判断

目的:"为了测试而设计接口"的特征。

三、关键问题解决方案

问题 1:模型会把"做了啥"当成记录

现象
复制代码
{
  "text": "做了啥",
  "author": "11"
}

模型早期会返回:

复制代码
action=record

导致大量低质量碎片污染数据。

解决策略(非纯 prompt)
  • 在 input 层增加最小事实门槛

  • 疑问句(做了啥 / 干了什么)→ 强制 query

  • 只有"事实 + 动作"才允许 record

目的**:不是"更聪明的模型",而是"更严格的入口约束"**

问题 2:confirm / reject 行为污染返回结果

现象
  • confirm 返回历史碎片

  • reject 偶尔返回残留数据

解决方案

在主流程中明确兜底:

复制代码
if action in (confirm, reject): today_fragments = []

这是 contract 稳定性问题,须用代码兜底,而不是指望模型。

四、接口测试用例设计(核心)

TC-01:author 必填校验

输入:

{ "text": "今天完成了测试" }

预期:

  • HTTP 400

  • error = missing author field


TC-02:事实记录

输入:

{ "text": "今天完成了WMS用例执行", "author": "张三" }

预期:

  • action = record

  • tool_called = record_fragment

  • today_fragments 只包含张三


TC-03:作者隔离查询

输入:

{ "text": "做了啥", "author": "李四" }

预期:

  • action = query

  • today_fragments = \[\]


TC-04:全量查询(all)

输入:

{ "text": "做了啥", "author": "all" }

预期:

  • 返回所有 author 的今日碎片

TC-05:reject 行为

输入:

{ "text": "帮我写个日报", "author": "张三" }

预期:

  • action = reject

  • tool_called = null

  • today_fragments = \[\]


TC-06:confirm 行为

输入:

{ "text": "帮我打卡", "author": "张三" }

预期:

  • action = confirm

  • tool_called = confirm_clock_event

  • today_fragments = \[\]

五、迭代二总结

解决三个问题:

  1. 模型不稳定 → 接口可控

  2. 多人混用 → 明确隔离

  3. 无法测试 → 明确 contract + 用例

下一步可以做:

  • 自动化接口回归(pytest / requests)

  • 历史数据清洗策略

  • 打卡规则的异常场景测试(超时 / 重复)

项目代码

本文对应代码为 项目一 · 迭代二最终封板版本:

https://github.com/test202005/project1/releases/tag/iter2-final

说明:

  • main 分支保留迭代一作为稳定基线

  • iter2-final 为多用户 + API 化后的工程增强版本(接口与行为已封板)

相关推荐
weixin_3077791317 分钟前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
Sinokap27 分钟前
OpenAI 披露 AI 安全实验:智能体如何突破隔离边界?
人工智能·安全
Dxy12393102161 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷1 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
云和数据.ChenGuang1 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain
重生之我在番茄自学网安拯救世界1 小时前
AI 开发者日报 第1期(本周精选)| 插件市场投毒、智能体搞出“官僚饥荒村”,十年前的 CNN 打赢大模型
人工智能·网络安全·大模型·ai编程·智能体
涛声依旧-底层原理研究所1 小时前
拆解 Cordis 底座:Agent 是如何被「组合」出来的
人工智能·架构
nice_lcj5202 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试
秦先生在广东2 小时前
记忆不再是黑盒
人工智能
秦先生在广东2 小时前
49个AI智能体接管你的游戏开发
人工智能