Skip to content

feat(provider): 项目进度自然语言摘要 endpoint —— MVP 版本 #2

Description

@ly-le

feat(provider): 项目进度自然语言摘要 endpoint —— MVP 版本

现状痛点

PMD(docs/pmd/index.md)已明确诊断:客户通过群聊反复询问项目进度。当前工程师需切换到群聊、查看任务列表后手动编写进度说明。src/provider/app/storage.py 中 demo 任务 e4(每周进度同步)即对应这一动作——该任务标记为 doing 状态,表明每个项目每周均需消耗工程师一次手工劳动。

现状:

  1. 工程师在内部系统操作任务状态(todo → doing → done)
  2. 客户无法查看内部系统,仅能通过群聊询问进度
  3. 工程师切换到群聊,查看任务列表后手动编写进度说明
  4. 该问题每周重复出现,工程师需重复编写

上述问题并非信息缺失——任务状态、所属阶段在 Provider 中均已存储,缺失的是"将状态变化自动转换为客户可理解的陈述"。

提案

为 Provider 新增 GET /projects/{id}/summary 接口,返回自然语言文本,描述该项目当前阶段、各任务完成情况、近一周内的状态变化。

所有信息均来自已有 Task 状态数据及 updated_at 字段,不新增数据采集基础设施。

极简技术方案

新增文件:src/provider/app/summarizer.py

from datetime import datetime, timedelta, timezone

# 阶段 → 描述模板
STAGE_MAP = {
    "agreement":   "项目处于商务约定阶段,正在确认合同与交付标准。",
    "execution":   "项目处于执行阶段,数据工程工作正在进行中。",
    "acceptance":  "项目处于验收阶段,交付物正在接受客户验证。",
}

# 状态 → 中文标签
STATUS_LABEL = {
    "todo": "待开始", "doing": "进行中", "done": "已完成", "blocked": "已阻塞",
}

def summarize_project(project_id: str, store: dict) -> str:
    ts = [t for t in store["tasks"].values() if t.project_id == project_id]
    now = datetime.now(timezone.utc)
    week_ago = now - timedelta(days=7)

    # Step 1: 推断当前阶段
    stage = _infer_stage(ts)

    # Step 2: 当前状态汇总
    summary = STAGE_MAP[stage] + "\n\n"
    summary += _current_status(ts)

    # Step 3: 本周变化(最近 7 天状态变更的任务)
    changed = [t for t in ts if t.updated_at and t.updated_at >= week_ago]
    if changed:
        summary += "\n**本周变化**:\n"
        for t in changed:
            summary += f"- {STATUS_LABEL.get(t.status, t.status)}{t.title}\n"

    return summary


def _infer_stage(tasks) -> str:
    if any(t.type == "execution" and t.status == "doing" for t in tasks):
        return "execution"
    if any(t.type == "acceptance" and t.status != "todo" for t in tasks):
        return "acceptance"
    return "agreement"


def _current_status(tasks) -> str:
    lines = []
    groups = {}
    for t in tasks:
        groups.setdefault(t.type, []).append(t)

    type_labels = {"requirement": "需求确认", "agreement": "商务约定",
                   "execution": "开发执行", "acceptance": "验收交付"}

    for ttype, items in groups.items():
        done = sum(1 for t in items if t.status == "done")
        lines.append(f"- {type_labels.get(ttype, ttype)}{done}/{len(items)} 项")
        for t in items:
            if t.status in ("doing", "blocked"):
                lines.append(f"  - [{STATUS_LABEL[t.status]}] {t.title}")
    return "\n".join(lines)

新增路由:src/provider/app/main.py(追加 3 行)

from app.summarizer import summarize_project

@app.get("/projects/{project_id}/summary")
async def project_summary(project_id: str):
    return {"project_id": project_id, "summary": summarize_project(project_id, store)}

MVP 的 Agent 和 RAG 降维定义

Agent 降维

完整版概念 MVP 降维后
多步骤自动决策、可调用工具 固定顺序的数据管道:读任务列表 → 按类型分组 → 匹配模板 → 拼接文本
自主推断下一步操作 零自主决策,不改变任何数据,仅做只读聚合

RAG 降维

完整版概念 MVP 降维后
向量检索 + LLM 生成自然语言回答 本 MVP 不涉及 RAG。进度摘要为预生成的推送文本,客户无需提问即可查看
对话式问答 若后续扩展为客户追问场景(如"某任务因何阻塞"),MVP RAG = 任务类型/状态关键词 → 固定解释模板的精确匹配,检索不到则返回"暂无更多信息",不得编造

人机分工底线

  • 自动化管道负责:读取已有状态 → 拼接摘要文本(事后描述)
  • 工程师负责:任务状态的更新判断(doing / done / blocked,事前决策)
  • 自动化管道不替代工程师进行任何"决定下一步操作"的判断

用户可见的变化

客户门户项目卡片旁展示自然语言摘要,替代仅展示原始任务列表。

示例输出:

电商平台用户行为分析 当前进度摘要:

项目处于执行阶段,数据工程工作正在进行中。

  • 需求确认:2/4 项
    • [进行中] 电商平台用户行为分析
    • [进行中] 变更:新增数据源字段
  • 商务约定:2/3 项
  • 开发执行:1/3 项
    • [进行中] 数据清理ETL开发
    • [进行中] 每周进度同步
  • 验收交付:0/3 项

本周变化

  • 已完成:数据探查与质量评估
  • 进行中:数据清理ETL开发

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions