Skill: tujinsama/conversion-path-optimizer-claw (version 1.0.0)

--- name: conversion-path-optimizer-claw description: | 转化路径优化虾 — 分析销售漏斗、挖掘高转化话术、给出优化建议的销售智能参谋。 **当以下情况时使用此 Skill**： (1) 需要分析销售漏斗各阶段转化率，找出流失卡点 (2) 需要从历史 CRM 数据或对话记录中提取高转化话术 (3) 需要对比不同时间段或不同销售团队的漏斗表现 (4) 需要根据客户画像（行业、规模、痛点）推荐个性化话术 (5) 需要设计 A/B 测试方案，量化话术效果 (6) 需要生成话术手册，培训新人销售 (7) 用户提到"转化率优化"、"销售话术"、"漏斗分析"、"成交路径"、"话术建议"、"转化提升"、"销售培训"、"客户流失"、"A/B测试"、"销售数据分析" --- # 转化路径优化虾 分析获客漏斗，挖掘高转化话术，帮助销售团队复制成功经验。 ## 工作流程 ``` [输入数据] → [数据清洗] → [漏斗建模] → [话术挖掘] → [效果评估] → [推荐输出] ``` ## 输入数据格式 **推荐字段（CSV/Excel）**： | 字段 | 说明 | 必填 | |------|------|------| | 客户ID / customer_id | 客户唯一标识 | 是 | | 阶段 / stage | lead/qualification/demo/negotiation/closed_won/closed_lost | 是 | | 话术内容 / script | 销售说的话 | 话术分析时必填 | | 客户反馈 / feedback | 客户回应 | 可选 | | 最终结果 / result | 成交/流失 | 话术分析时必填 | | 日期 / date | 沟通时间 | 时间段分析时必填 | **自然语言输入**：也可直接描述问题，如"最近转化率下降了，帮我分析原因"。 ## 使用脚本 ### 漏斗分析 ```bash # 分析最近 30 天漏斗（对比 SaaS 行业基准） python scripts/analyze-funnel.py analyze --input data.csv --days 30 --industry SaaS # 对比两个月份 python scripts/analyze-funnel.py compare --input data.csv --period1 2026-03 --period2 2026-02 # 导出 HTML 报告 python scripts/analyze-funnel.py export --input data.csv --format html --output report.html ``` ### 话术提取 ```bash # 提取 Top 10 高频成交话术 python scripts/extract-scripts.py extract --input data.csv --top 10 # 按转化率排序话术 python scripts/extract-scripts.py rank --input data.csv # 推荐价格异议话术 python scripts/extract-scripts.py recommend --input data.csv --scenario price_objection # 可用场景: price_objection | competitor | delay | demo | closing ``` **依赖**：`pip install pandas openpyxl` ## 参考资料 根据任务按需读取： - **漏斗建模、转化率基准、流失预警** → `references/funnel-modeling.md` - **话术挖掘算法、对话结构分析** → `references/script-mining.md` - **A/B 测试设计、话术评分模型** → `references/script-evaluation.md` - **各行业话术模板（SaaS/电商/B2B）** → `references/industry-templates.md` ## 输出格式 根据用户需求选择输出形式： 1. **漏斗分析报告**：各阶段转化率 + 流失卡点 + 优化建议 2. **话术推荐列表**：按场景分类，附转化率数据支撑 3. **话术手册**：结构化 Markdown，可直接用于培训 4. **飞书文档**：调用 `feishu_create_doc` 生成正式文档 ## 注意事项 - 建议至少 100 条成交记录才能产生有效统计洞察 - 话术推荐是统计规律，需结合具体客户灵活调整 - 数据中的客户敏感信息（姓名、手机）建议脱敏后再分析

path: references/funnel-modeling.md
content: # 销售漏斗建模指南

## 标准漏斗阶段

| 阶段 | 英文标识 | 说明 |
|------|----------|------|
| 初次接触 | lead | 首次触达客户 |
| 需求确认 | qualification | 确认客户有真实需求 |
| 方案演示 | demo | 产品演示/方案讲解 |
| 报价谈判 | negotiation | 价格与条款谈判 |
| 合同签订 | closed_won | 成交 |
| 流失 | closed_lost | 未成交 |

不同行业可自定义阶段，但需保持字段一致性。

## 转化率计算

```
阶段转化率 = 进入下一阶段数 / 本阶段总数 × 100%
整体转化率 = closed_won 数 / lead 总数 × 100%
```

## 行业健康转化率基准

| 行业 | lead→qualification | qualification→demo | demo→negotiation | negotiation→closed_won |
|------|-------------------|-------------------|-----------------|----------------------|
| SaaS | 40-60% | 50-70% | 60-80% | 20-40% |
| 电商 | 30-50% | 60-80% | 70-90% | 30-60% |
| B2B | 20-40% | 40-60% | 50-70% | 15-30% |

## 流失预警信号

- 某阶段转化率低于行业基准 20% 以上 → 重点排查
- 单阶段停留时间超过平均值 2 倍 → 客户可能失温
- 同一销售的流失率持续高于团队均值 → 需要话术辅导

## 异常检测规则

1. **骤降型**：某阶段转化率环比下降 >15%，需立即分析原因
2. **长尾型**：大量客户卡在同一阶段超过 30 天，需优化该阶段话术
3. **季节型**：结合历史数据判断是否为正常季节性波动


path: references/industry-templates.md
content: # 行业话术模板库

## SaaS 行业

### 开场白
> "您好，我注意到贵公司在 [痛点领域] 上有一些挑战，我们有几个客户和您情况类似，他们用了我们的方案后 [具体成果]，我想花 10 分钟了解一下您的情况，看看是否适合。"

### 价值呈现
> "我们帮 [同类客户] 在 [时间] 内实现了 [ROI 数据]。以您目前的规模来算，大概能节省 [具体数字]。"

### 价格异议
> "我理解价格是重要考量。我们来算一笔账：您现在每月在 [问题] 上花费约 [X]，用了我们的方案后可以减少到 [Y]，6 个月就能回本。"

### 临门一脚
> "我们现在有一个 [限时优惠/免费试用] 的机会，很多客户都是先试用 2 周确认效果再签约的，要不要先体验一下？"

---

## 电商行业

### 开场白
> "您好，我看到您最近在关注 [产品类目]，我们这款产品目前有 [X] 位买家好评，特别适合 [使用场景]。"

### 价格异议
> "这个价格包含了 [X 天售后/免费退换/赠品]，算下来比同类产品实惠很多。而且现在下单还有 [优惠]。"

### 临门一脚
> "这款库存不多了，今天下单还能赶上 [节日/活动] 前到货，要不要先锁定一个？"

---

## B2B 行业

### 需求挖掘（SPIN 法）
- **现状问题**："您目前 [业务流程] 是怎么做的？"
- **痛点问题**："这个方式有没有遇到过 [常见痛点]？"
- **影响问题**："这个问题对您的 [业务目标] 有多大影响？"
- **价值问题**："如果能解决这个问题，对您来说意味着什么？"

### 竞品对比
> "我们和 [竞品] 的核心区别在于 [差异化优势]。您最看重的是 [功能/价格/服务]？我们在这方面 [具体优势]。"

### 决策链应对
> "我理解这个决策需要多方确认。我可以准备一份针对 [决策者角色] 的材料，帮您内部推进，您觉得哪些点是他们最关心的？"

### 风险消除
> "我们提供 [X 个月] 的效果保障，如果达不到约定目标，[退款/延期服务]。这样您的风险是可控的。"


path: references/script-evaluation.md
content: # 话术效果评估框架

## 核心指标

| 指标 | 计算方式 | 说明 |
|------|----------|------|
| 话术转化率 | 使用该话术后成交数 / 使用总次数 | 核心指标 |
| 使用频率 | Top Sales 使用次数 | 验证话术的实战价值 |
| 平均成交周期 | 使用该话术后平均成交天数 | 越短越好 |
| 适用客户类型 | 按行业/规模/痛点分类统计 | 精准匹配场景 |

## A/B 测试设计

1. **分组**：随机将客户分为 A/B 两组，分别使用不同话术
2. **样本量**：每组至少 50 个有效对话，确保统计显著性
3. **控制变量**：确保两组客户画像相似（行业、规模、来源渠道）
4. **评估周期**：至少观察 2 周，避免短期波动干扰
5. **显著性检验**：使用卡方检验，p < 0.05 才认为差异显著

## 话术评分模型

综合评分 = 转化率 × 0.5 + 使用频率得分 × 0.3 + 成交周期得分 × 0.2

- 转化率得分：直接使用百分比
- 使用频率得分：归一化到 0-100
- 成交周期得分：100 - (实际周期/平均周期 × 100)，越短得分越高

## 时间衰减策略

话术效果会随市场变化而衰减：
- 每季度重新评估话术库
- 转化率下降 >10% 的话术标记为"待更新"
- 新增数据超过 200 条时触发自动重新排序


path: references/script-mining.md
content: # 话术挖掘算法库

## 核心方法

### 1. 高频短语提取（TF-IDF）

从成交对话中提取高频关键短语：
- 计算每个短语在成交对话中的 TF-IDF 值
- 对比流失对话，找出成交对话中显著高频的短语
- 这些短语即为候选高转化话术

### 2. 对话结构分析

识别"问题-回答-反馈"模式：
```
客户提出异议 → 销售应对 → 客户反馈（积极/消极）
```
统计哪些应对方式获得积极反馈的比例最高。

### 3. 情感倾向判断

客户情感状态分类：
- **积极**：表达兴趣、认可、追问细节
- **犹豫**：要求对比、询问竞品、拖延决策
- **抗拒**：明确拒绝、价格异议、功能质疑

针对不同情感状态，推荐不同话术策略。

## 话术分类体系

| 场景 | 触发信号 | 推荐策略 |
|------|----------|----------|
| 开场白 | 首次接触 | 建立信任、快速定位需求 |
| 需求挖掘 | qualification 阶段 | SPIN 提问法 |
| 价值呈现 | demo 阶段 | 案例+ROI 量化 |
| 价格异议 | "太贵了" | 价值对比、分期方案、ROI 计算 |
| 竞品对比 | "我们在看 XX" | 差异化优势、客户证言 |
| 拖延决策 | "再考虑考虑" | 限时优惠、风险消除 |
| 临门一脚 | negotiation 阶段末期 | 小步骤承诺、试用方案 |

## 数据质量要求

- 建议最少 100 条成交记录才能产生有效统计
- 对话记录需包含：时间戳、发言方（销售/客户）、内容
- 去除测试账号、内部沟通记录


path: scripts/analyze-funnel.py
content: #!/usr/bin/env python3
"""
漏斗分析脚本 - 计算各阶段转化率，输出分析报告
用法:
  python analyze-funnel.py analyze --input data.csv [--days 30]
  python analyze-funnel.py compare --input data.csv --period1 2026-03 --period2 2026-02
  python analyze-funnel.py export --input data.csv --format html --output report.html
"""

import argparse
import sys
from datetime import datetime, timedelta

try:
    import pandas as pd
except ImportError:
    print("缺少依赖: pip install pandas")
    sys.exit(1)

STAGE_ORDER = ["lead", "qualification", "demo", "negotiation", "closed_won", "closed_lost"]
STAGE_LABELS = {
    "lead": "初次接触",
    "qualification": "需求确认",
    "demo": "方案演示",
    "negotiation": "报价谈判",
    "closed_won": "成交",
    "closed_lost": "流失",
}

# 行业健康转化率基准（各阶段下限）
BENCHMARKS = {
    "SaaS":  {"lead→qualification": 0.40, "qualification→demo": 0.50, "demo→negotiation": 0.60, "negotiation→closed_won": 0.20},
    "电商":  {"lead→qualification": 0.30, "qualification→demo": 0.60, "demo→negotiation": 0.70, "negotiation→closed_won": 0.30},
    "B2B":   {"lead→qualification": 0.20, "qualification→demo": 0.40, "demo→negotiation": 0.50, "negotiation→closed_won": 0.15},
}


def load_data(path: str) -> pd.DataFrame:
    """加载 CSV/Excel 数据，自动识别格式"""
    if path.endswith(".csv"):
        df = pd.read_csv(path)
    else:
        df = pd.read_excel(path)
    # 标准化列名（兼容中英文）
    col_map = {}
    for col in df.columns:
        lc = col.lower().strip()
        if lc in ("stage", "阶段", "沟通阶段"):
            col_map[col] = "stage"
        elif lc in ("date", "日期", "时间", "create_time"):
            col_map[col] = "date"
        elif lc in ("result", "结果", "最终结果"):
            col_map[col] = "result"
        elif lc in ("customer_id", "客户id", "客户编号"):
            col_map[col] = "customer_id"
    df = df.rename(columns=col_map)
    if "date" in df.columns:
        df["date"] = pd.to_datetime(df["date"], errors="coerce")
    return df


def compute_funnel(df: pd.DataFrame) -> dict:
    """计算漏斗各阶段人数和转化率"""
    counts = {}
    for stage in STAGE_ORDER:
        counts[stage] = len(df[df["stage"] == stage]) if "stage" in df.columns else 0

    # 如果有 result 列，用 result 判断 closed_won/closed_lost
    if "result" in df.columns:
        counts["closed_won"] = len(df[df["result"].str.contains("成交|won|closed_won", case=False, na=False)])
        counts["closed_lost"] = len(df[df["result"].str.contains("流失|lost|closed_lost", case=False, na=False)])

    transitions = [
        ("lead", "qualification"),
        ("qualification", "demo"),
        ("demo", "negotiation"),
        ("negotiation", "closed_won"),
    ]
    rates = {}
    for src, dst in transitions:
        key = f"{src}→{dst}"
        if counts.get(src, 0) > 0:
            rates[key] = counts.get(dst, 0) / counts[src]
        else:
            rates[key] = None
    return {"counts": counts, "rates": rates}


def print_funnel_report(funnel: dict, industry: str = None):
    """打印漏斗分析报告"""
    counts = funnel["counts"]
    rates = funnel["rates"]
    benchmark = BENCHMARKS.get(industry, {}) if industry else {}

    print("\n" + "=" * 50)
    print("📊 销售漏斗分析报告")
    print("=" * 50)
    for stage in STAGE_ORDER:
        label = STAGE_LABELS.get(stage, stage)
        n = counts.get(stage, 0)
        print(f"  {label:8s}: {n:4d} 条")

    print("\n📈 各阶段转化率")
    print("-" * 40)
    for key, rate in rates.items():
        if rate is None:
            print(f"  {key}: 数据不足")
            continue
        pct = f"{rate*100:.1f}%"
        bench = benchmark.get(key)
        if bench and rate < bench:
            flag = f"⚠️  低于基准({bench*100:.0f}%)"
        else:
            flag = "✅"
        print(f"  {key}: {pct:6s} {flag}")

    total_lead = counts.get("lead", 0)
    total_won = counts.get("closed_won", 0)
    if total_lead > 0:
        overall = total_won / total_lead
        print(f"\n🎯 整体转化率: {overall*100:.1f}%  ({total_won}/{total_lead})")
    print("=" * 50)


def cmd_analyze(args):
    df = load_data(args.input)
    if args.days and "date" in df.columns:
        cutoff = datetime.now() - timedelta(days=args.days)
        df = df[df["date"] >= cutoff]
        print(f"筛选最近 {args.days} 天数据，共 {len(df)} 条")
    funnel = compute_funnel(df)
    print_funnel_report(funnel, industry=getattr(args, "industry", None))


def cmd_compare(args):
    df = load_data(args.input)
    results = {}
    for period_str in [args.period1, args.period2]:
        if "date" in df.columns:
            sub = df[df["date"].dt.to_period("M").astype(str) == period_str]
        else:
            sub = df
        results[period_str] = compute_funnel(sub)
        print(f"\n【{period_str}】")
        print_funnel_report(results[period_str])

    # 对比转化率变化
    print("\n📊 转化率对比（period1 vs period2）")
    print("-" * 40)
    r1 = results[args.period1]["rates"]
    r2 = results[args.period2]["rates"]
    for key in r1:
        v1 = r1.get(key)
        v2 = r2.get(key)
        if v1 is not None and v2 is not None:
            delta = (v1 - v2) * 100
            arrow = "↑" if delta > 0 else "↓"
            print(f"  {key}: {v2*100:.1f}% → {v1*100:.1f}%  {arrow}{abs(delta):.1f}pp")


def cmd_export(args):
    df = load_data(args.input)
    funnel = compute_funnel(df)
    counts = funnel["counts"]
    rates = funnel["rates"]

    if args.format == "html":
        rows = ""
        for stage in STAGE_ORDER:
            label = STAGE_LABELS.get(stage, stage)
            n = counts.get(stage, 0)
            rows += f"<tr><td>{label}</td><td>{n}</td></tr>\n"
        rate_rows = ""
        for key, rate in rates.items():
            pct = f"{rate*100:.1f}%" if rate is not None else "N/A"
            rate_rows += f"<tr><td>{key}</td><td>{pct}</td></tr>\n"
        html = f"""<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>漏斗分析报告</title>
<style>body{{font-family:sans-serif;padding:20px}}table{{border-collapse:collapse;width:100%}}
th,td{{border:1px solid #ddd;padding:8px;text-align:left}}th{{background:#f2f2f2}}</style>
</head><body>
<h1>销售漏斗分析报告</h1>
<h2>各阶段数量</h2>
<table><tr><th>阶段</th><th>数量</th></tr>{rows}</table>
<h2>转化率</h2>
<table><tr><th>路径</th><th>转化率</th></tr>{rate_rows}</table>
</body></html>"""
        with open(args.output, "w", encoding="utf-8") as f:
            f.write(html)
        print(f"✅ 报告已导出: {args.output}")
    else:
        print_funnel_report(funnel)
        print(f"（纯文本模式，如需 HTML 请指定 --format html）")


def main():
    parser = argparse.ArgumentParser(description="销售漏斗分析工具")
    sub = parser.add_subparsers(dest="cmd")

    p_analyze = sub.add_parser("analyze", help="分析漏斗数据")
    p_analyze.add_argument("--input", required=True, help="数据文件路径 (CSV/Excel)")
    p_analyze.add_argument("--days", type=int, help="只分析最近 N 天")
    p_analyze.add_argument("--industry", choices=["SaaS", "电商", "B2B"], help="行业基准对比")

    p_compare = sub.add_parser("compare", help="对比两个时间段")
    p_compare.add_argument("--input", required=True)
    p_compare.add_argument("--period1", required=True, help="格式: 2026-03")
    p_compare.add_argument("--period2", required=True, help="格式: 2026-02")

    p_export = sub.add_parser("export", help="导出报告")
    p_export.add_argument("--input", required=True)
    p_export.add_argument("--format", choices=["html", "text"], default="html")
    p_export.add_argument("--output", default="funnel-report.html")

    args = parser.parse_args()
    if args.cmd == "analyze":
        cmd_analyze(args)
    elif args.cmd == "compare":
        cmd_compare(args)
    elif args.cmd == "export":
        cmd_export(args)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()


path: scripts/extract-scripts.py
content: #!/usr/bin/env python3
"""
话术提取脚本 - 从对话记录中挖掘高转化话术
用法:
  python extract-scripts.py extract --input data.csv [--top 10]
  python extract-scripts.py rank --input data.csv
  python extract-scripts.py recommend --input data.csv --scenario price_objection
"""

import argparse
import sys
import re
from collections import Counter

try:
    import pandas as pd
except ImportError:
    print("缺少依赖: pip install pandas")
    sys.exit(1)

SCENARIOS = {
    "price_objection": ["太贵", "贵了", "价格", "预算", "费用", "cost", "price"],
    "competitor": ["竞品", "对比", "其他家", "XX公司", "competitor"],
    "delay": ["再考虑", "考虑一下", "回头", "下次", "不急", "think about"],
    "demo": ["演示", "demo", "试用", "看看效果", "功能"],
    "closing": ["签合同", "下单", "付款", "合作", "确认"],
}

SCENARIO_LABELS = {
    "price_objection": "价格异议",
    "competitor": "竞品对比",
    "delay": "拖延决策",
    "demo": "方案演示",
    "closing": "临门一脚",
}


def load_data(path: str) -> pd.DataFrame:
    if path.endswith(".csv"):
        df = pd.read_csv(path)
    else:
        df = pd.read_excel(path)
    col_map = {}
    for col in df.columns:
        lc = col.lower().strip()
        if lc in ("script", "话术", "话术内容", "content", "沟通内容"):
            col_map[col] = "script"
        elif lc in ("result", "结果", "最终结果"):
            col_map[col] = "result"
        elif lc in ("stage", "阶段", "沟通阶段"):
            col_map[col] = "stage"
        elif lc in ("feedback", "客户反馈", "反馈"):
            col_map[col] = "feedback"
        elif lc in ("sales_id", "销售id", "销售编号"):
            col_map[col] = "sales_id"
    return df.rename(columns=col_map)


def is_won(result_val) -> bool:
    if pd.isna(result_val):
        return False
    return bool(re.search(r"成交|won|closed_won|✅", str(result_val), re.IGNORECASE))


def detect_scenario(text: str) -> str:
    """检测话术所属场景"""
    text_lower = str(text).lower()
    for scenario, keywords in SCENARIOS.items():
        if any(kw in text_lower for kw in keywords):
            return scenario
    return "general"


def cmd_extract(args):
    df = load_data(args.input)
    if "script" not in df.columns:
        print("❌ 未找到话术列，请确保数据包含 '话术内容' 或 'script' 列")
        sys.exit(1)

    # 只取成交记录
    if "result" in df.columns:
        won_df = df[df["result"].apply(is_won)]
    else:
        won_df = df
        print("⚠️  未找到结果列，将分析全部记录")

    print(f"\n✅ 成交记录: {len(won_df)} 条（共 {len(df)} 条）")

    # 提取所有话术片段（按句号/换行分割）
    all_scripts = []
    for _, row in won_df.iterrows():
        text = str(row.get("script", ""))
        sentences = re.split(r"[。！？\n]", text)
        for s in sentences:
            s = s.strip()
            if len(s) > 10:  # 过滤太短的片段
                all_scripts.append(s)

    # 统计高频话术
    counter = Counter(all_scripts)
    top_scripts = counter.most_common(args.top)

    print(f"\n🏆 Top {args.top} 高频话术（来自成交记录）")
    print("=" * 60)
    for i, (script, count) in enumerate(top_scripts, 1):
        scenario = detect_scenario(script)
        label = SCENARIO_LABELS.get(scenario, "通用")
        print(f"\n{i}. [{label}] 出现 {count} 次")
        print(f"   {script[:100]}{'...' if len(script) > 100 else ''}")
    print("=" * 60)


def cmd_rank(args):
    df = load_data(args.input)
    if "script" not in df.columns or "result" not in df.columns:
        print("❌ 需要 '话术内容' 和 '结果' 两列")
        sys.exit(1)

    # 按话术统计转化率
    script_stats = {}
    for _, row in df.iterrows():
        text = str(row.get("script", "")).strip()
        if not text or len(text) < 10:
            continue
        won = is_won(row.get("result"))
        if text not in script_stats:
            script_stats[text] = {"total": 0, "won": 0}
        script_stats[text]["total"] += 1
        if won:
            script_stats[text]["won"] += 1

    # 过滤样本量太少的
    ranked = [
        (s, v["won"] / v["total"], v["total"])
        for s, v in script_stats.items()
        if v["total"] >= 3
    ]
    ranked.sort(key=lambda x: x[1], reverse=True)

    print(f"\n📊 话术转化率排行（样本量 ≥ 3）")
    print("=" * 60)
    for i, (script, rate, total) in enumerate(ranked[:20], 1):
        scenario = detect_scenario(script)
        label = SCENARIO_LABELS.get(scenario, "通用")
        print(f"\n{i}. [{label}] 转化率 {rate*100:.0f}%（{int(rate*total)}/{total}）")
        print(f"   {script[:100]}{'...' if len(script) > 100 else ''}")
    print("=" * 60)


def cmd_recommend(args):
    df = load_data(args.input)
    scenario = args.scenario

    if scenario not in SCENARIOS:
        print(f"❌ 未知场景: {scenario}")
        print(f"可用场景: {', '.join(SCENARIOS.keys())}")
        sys.exit(1)

    keywords = SCENARIOS[scenario]
    label = SCENARIO_LABELS.get(scenario, scenario)

    # 筛选包含场景关键词的话术
    if "script" in df.columns:
        mask = df["script"].apply(
            lambda x: any(kw in str(x).lower() for kw in keywords)
        )
        scenario_df = df[mask]
    else:
        scenario_df = df

    if "result" in df.columns:
        won_df = scenario_df[scenario_df["result"].apply(is_won)]
    else:
        won_df = scenario_df

    print(f"\n🎯 场景：{label}")
    print(f"   匹配记录: {len(scenario_df)} 条，其中成交: {len(won_df)} 条")

    if len(won_df) == 0:
        print("   暂无足够的成交数据，推荐使用行业模板（见 references/industry-templates.md）")
        return

    # 提取成交话术
    scripts = []
    for _, row in won_df.iterrows():
        text = str(row.get("script", "")).strip()
        if len(text) > 10:
            scripts.append(text)

    counter = Counter(scripts)
    print(f"\n💡 推荐话术（基于 {len(won_df)} 条成交记录）")
    print("=" * 60)
    for i, (script, count) in enumerate(counter.most_common(5), 1):
        print(f"\n{i}. 出现 {count} 次")
        print(f"   {script[:150]}{'...' if len(script) > 150 else ''}")
    print("=" * 60)


def main():
    parser = argparse.ArgumentParser(description="话术提取与推荐工具")
    sub = parser.add_subparsers(dest="cmd")

    p_extract = sub.add_parser("extract", help="提取高频话术")
    p_extract.add_argument("--input", required=True)
    p_extract.add_argument("--top", type=int, default=10)

    p_rank = sub.add_parser("rank", help="按转化率排序话术")
    p_rank.add_argument("--input", required=True)

    p_recommend = sub.add_parser("recommend", help="推荐指定场景话术")
    p_recommend.add_argument("--input", required=True)
    p_recommend.add_argument(
        "--scenario",
        required=True,
        choices=list(SCENARIOS.keys()),
        help=f"场景: {', '.join(SCENARIOS.keys())}",
    )

    args = parser.parse_args()
    if args.cmd == "extract":
        cmd_extract(args)
    elif args.cmd == "rank":
        cmd_rank(args)
    elif args.cmd == "recommend":
        cmd_recommend(args)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)