需求背景与架构选择
团队内部一直有个老问题:周五下午大家花大量时间拼凑周报。现有的 OA 系统只提供空白模板,填完还是得自己组织语言,最后交上去的内容往往流水账化,管理层也看不出实际产出。
我的思路是:把周报拆解为"数据收集 → 语义重组 → 结构化输出 → 人工复核"四个环节。前三个环节交给 AI 完成,第四个环节保留给开发者。这样既不试图让模型代替人做业务判断,也能把重复劳动降到最低。
技术选型上,我们项目是 Spring Boot 生态,所以自然倾向使用 Spring AI 作为大模型接入层。Spring AI 提供了统一的 ChatModel 接口,底层可以平滑替换供应商,这对企业级应用很关键。模型侧我使用了阿里百炼平台的通义千问系列。关于选题中提到的"Qwen3.8",目前百炼公开文档中主要使用 qwen-max、qwen-plus、qwen-turbo 等命名,3.8 可能是特定渠道或内部版本号。以下实践基于 DashScope 标准 API,参数与行为表现已对齐主流 Qwen3 系列能力。如果你手头有确切版本映射,只需替换 model 字段即可,整体调用链路不变。
数据预处理与上下文组装

大模型的效果很大程度上取决于喂给它什么。直接丢一堆 Git Log 进去,模型要么漏掉关键信息,要么被无关的依赖升级记录带偏。
我写了一个轻量级的数据清洗管道,逻辑如下:
- 拉取上周的 Git 提交记录。只保留
--since="1 week ago"且author为本团队成员的节点。 - 过滤非业务提交:正则匹配
merge、chore、deps:、style:开头的 commit message,直接丢弃。 - 提取结构化字段:模块名、变更类型(feat/fix/refactor)、关联的需求 ID(从 message 末尾的
#TASK-123提取)。 - 拼接任务详情:通过内部 Jira API 拿到对应 Task 的标题和当前状态。
清洗后的数据会转成 Markdown 表格,作为 System Prompt 的一部分。这里有个实际观察:上下文窗口不是越大越好。我测试过保留全部 30+ 条变更记录,模型输出的摘要反而变得冗长且重点分散。最终改为只保留本周新增的核心任务(最多 8 条),并在每条任务后附加一句简短的"业务影响说明"(这部分由开发自己在填写任务时录入,AI 负责抽取)。
yaml
# application.yml 片段
spring:
ai:
chat:
client:
enabled: true
dashscope:
api-key: sk-xxxxxxxxxxxxxxx
chat:
options:
model: qwen-plus
temperature: 0.3
temperature 设为 0.3 是因为周报属于事实陈述类任务,不需要创造性发散。稍高的温度会导致同一份日志生成出不同风格的措辞,不利于团队统一汇报口径。这一点我没有在极端场景下验证,但在常规迭代节奏中表现稳定。
Spring AI 接入与结构化输出实现

传统的大模型调用是直接返回字符串,但我们需要的是前端能渲染的"确认卡"。这意味着输出必须是严格的结构化数据,最好是 JSON。
Spring AI 1.0+ 提供了 JsonSchemaOutputConverter,可以直接将 Java DTO 映射为 JSON Schema,并强制模型按该 Schema 输出。这比在 Prompt 里反复强调"请用 JSON 格式"要可靠得多。
核心 DTO 定义如下:
java
public record WeeklyReportCard(
String weekPeriod,
List<WorkItem> accomplishments,
String nextWeekPlan,
Map<String, Object> metadata
) {}
public record WorkItem(
String taskId,
String module,
String type,
String description,
String impact
) {}
调用逻辑使用 Spring AI 的 ChatClient 链式 API:
java
String schema = JsonSchemaGenerator.generateJsonSchema(WeeklyReportCard.class);
ChatRequest request = ChatRequest.builder()
.messages(new UserMessage("根据以下本周工作记录生成周报草稿:" + contextMarkdown))
.parameters(ChatOptions.builder()
.model("qwen-plus")
.temperature(0.3)
.outputConverter(new JsonSchemaOutputConverter(WeeklyReportCard.class))
.build())
.build();
WeeklyReportCard reportCard = chatClient.call(request);
JsonSchemaOutputConverter 会在请求头中注入严格的字段约束,模型若输出缺失字段或类型错误,会被拦截并抛出异常。我在本地加了重试机制:捕获解析异常后,截取模型返回的 JSON 片段进行二次格式化,最多重试两次。通常第一次就能拿到干净的数据。
这里的关键在于"为什么这么写"。如果不走 Schema 强约束,模型经常会在 JSON 外面包一层 Markdown 代码块(json ... ),或者多输出一个逗号导致 Jackson 反序列化失败。硬靠正则去清洗不仅脆弱,还会破坏数据结构。走 Spring AI 内置转换器,虽然初期配置稍微繁琐一点,但后期维护成本低很多。
"人工确认卡"交互闭环设计

拿到 WeeklyReportCard 对象后,后端不会直接存库或发送通知,而是将其序列化为一张"确认卡"推送到前端。
前后端的契约约定如下:
json
{
"cardId": "c_7f8a9b2c",
"status": "PENDING_REVIEW",
"data": { ... },
"createdAt": "2024-05-24T18:00:00Z"
}
前端收到后,渲染成一个可交互的卡片组件。每个 WorkItem 支持行内编辑,允许开发者增删改查条目。底部有两个操作按钮:"确认提交"和"申请重写"。
当点击"申请重写"时,前端会将用户的修改意见拼接成一条新的 User Message,携带原 cardId 和修改上下文,再次调用相同的生成接口。后端通过 Redis 暂存本次会话的 SystemMessage 历史,确保模型知道是基于上一版调整,而不是从零开始瞎编。
这种设计把控制权交还给人类。AI 负责提供初稿和快速重组信息,人类负责校准事实边界和业务权重。在实际运行中,大约 80% 的卡片只需微调 1~2 处即可确认,真正需要完全重写的不到 10%。
关键问题排查与调优

推进过程中遇到了几个比较典型的问题,记录下来供参考。
1. JSON 结构漂移与容错处理
即使用了 JsonSchemaOutputConverter,极少数情况下模型仍会违反约束。我在网关层加了一层防御性解析:先用 ObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 关闭严格校验,再用自定义的 BeanDeserializerModifier 补全默认值。这样即使用户输入了非常规任务描述,卡片也不会直接崩溃。
2. 长上下文下的注意力衰减
当某周提交了超过 50 个有效 commit 时,单纯拼接 Markdown 会让 Prompt 膨胀到 6k Token 以上。我测试后发现,Qwen 在 8k 窗口内的首尾记忆较强,中间段落容易被压缩。后来改为分模块生成:先按 module 分组,分别调用一次生成各模块摘要,最后在 Prompt 末尾加一句"请合并以下模块摘要,保持统一语气",再进行一次轻量级聚合。虽然增加了两次 API 调用,但输出质量显著提升。
3. 成本控制与缓存策略
通义千问按 token 计费,频繁调用会产生可观开销。我在入参阶段做了哈希缓存:将 GitLogHash + JiraTicketIds 排序后计算 MD5。若同一组合在一小时内重复触发,直接返回缓存的 JSON。对于日常迭代,重复率很高,这一步大概能节省 30% 左右的调用次数。
4. 关于 Qwen3.8 的特定参数
这一点我没有验证:部分内部文档提到 3.8 版本对中文业务术语的识别阈值有所下调。如果你确实在使用该特定版本,建议将 top_p 降至 0.8 以下以抑制冗余修饰词。公开版本的 qwen-plus 表现已能满足基础需求,具体差异需结合你们的实际评测集确认。
实际落地评估与后续方向
这套方案上线一个月后,团队反馈比较一致:写周报的时间从平均 25 分钟缩短到 6 分钟左右,但并没有出现"全自动代写"带来的信任危机。因为"确认卡"的存在,每个人都在最终提交前过了一遍内容,反而促使大家平时更注意规范 commit message 和任务描述。
从工程角度看,有几个取舍值得注意:
- 不要追求 100% 自动化。AI 擅长信息聚合与排版,但不擅长判断业务优先级。保留人工确认环节是必须的。
- Prompt 优于调参。对于事实型任务,温度系数已经压到最低,继续调参意义不大。把精力花在清洗脏数据、规范输入格式、设计清晰的 JSON Schema 上,收益更高。
- 监控不可省略 。接入 LLM 后,必须记录每次请求的
input_tokens、output_tokens、latency以及最终解析结果。我在 Grafana 上加了看板,方便追踪哪些周的上下文过长导致超时,哪些 commit 描述太模糊导致生成失败。
接下来准备做的两件事:一是把确认卡的修改记录沉淀为微调数据集,未来尝试在本地部署一个小参数模型做私有化推理,彻底规避网络延迟和数据外泄顾虑;二是探索与 CI/CD 流水线打通,当 PR 合并触发事件时自动预生成周报草稿,推到钉钉/企微待办审批流中。
如果你也在做类似的内部提效工具,建议先从"半自动确认"切入,跑通数据流转后再考虑全链路自动化。大模型不是银弹,但它确实能把工程师从低价值的文字搬运中解放出来,把时间留给真正需要思考的部分。