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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions