AI 帮你做总结:文本聚类后,如何用 DeepSeek 批量实现语义对齐?

5 阅读6分钟

📌 背景:13 个簇,每个叫什么名字?

在上一篇文章中,我用层次聚类 + 轮廓系数把 2000+ 个服务要素聚成了 13 个主题簇。

但现在面临一个新问题:这 13 个簇分别叫什么名字?

比如簇 6,里面有这些要素:

  • 温度不适、空调过冷、闷热、冷气过强、车厢温度、制冷不足...

人工看完可以总结为"空调温度问题"。但 13 个簇一个一个看,太慢了。

我需要一种方法:输入一个簇的所有要素,自动输出一个标准化的名称。

这就是"语义对齐"——让 LLM 理解一个簇的语义核心,并用统一的格式表达出来。

🏷️ 语义对齐设计

我设计了一套标准化的输出格式:

text

乘客 + (类型) + 核心问题

类型有三种:

  • (需求) :乘客主动提出的改进需求
  • (问题) :乘客反映的现存问题
  • (评价) :乘客表达的服务评价

示例:

  • 乘客(问题)空调温度不适
  • 乘客(评价)赞赏暖心毕业祝福
  • 乘客(需求)增加高峰班次

这样设计的好处:

  1. 主语统一:都是"乘客",视角一致
  2. 类型明确:一看就知道是问题、需求还是评价
  3. 格式固定:方便后续统计和展示
  4. 可操作性强:运营方可以直接根据类型采取行动

🛠️ 提示词设计

我设计的提示词包含以下几个部分:

prompt = f"""
请将以下关于地铁服务的乘客反馈提炼为最核心的标准化表述,要求:
1. 输出仅一条标准化表述
2. 只保留最本质的需求/问题/感受
3. 使用"乘客"作为主语
4. 采用"乘客+核心诉求"的极简结构
5. 不要包含具体线路、时段等细节

【输出规范】
1. 格式:严格遵循"乘客+[诉求类型]+[核心问题]"结构
2. 长度:不超过20个汉字(含标点)
3. 诉求类型标注:
   - (需求) 乘客主动提出的改进需求
   - (问题) 乘客反映的现存问题  
   - (评价) 乘客表达的服务评价
4. 必须包含最高频核心词
5. 优先选择出现频率最高的诉求类型

【优化原则】
1. 聚焦可行动项(运营方可直接解决的问题)
2. 保留程度副词(如"过度拥挤"vs"轻微拥挤")
3. 区分问题类型(设施/服务/管理等)
4. 消除模糊表述(如"改善服务"→"增加安检速度")

【典型范例】
好的输出:
"乘客(需求)增加高峰班次"
"乘客(问题)闸机故障率高"  
"乘客(评价)赞赏问询服务"
"乘客(评价)赞赏暖心毕业祝福"

差的输出:
"希望改进"(缺少主语和类型)
"3号线太挤"(含具体线路)

待分析文本:
{texts}

【最终输出】(只需返回标准表述,不要解释):
"""

📊 对齐结果展示

运行语义对齐后,13 个簇的标准表述如下:

簇 ID要素数标准化表述类型
1152乘客(评价)乘车环境舒适评价
2161乘客(评价)赞赏工作人员贴心服务评价
3183乘客(评价)出行高效便捷评价
4438乘客(评价)赞赏文化创意活动评价
5546乘客(评价)赞赏暖心毕业祝福评价
6584乘客(问题)空调温度不适问题
7390乘客(问题)车厢过度拥挤问题
8295乘客(问题)电梯扶梯设施不足问题
9179乘客(问题)列车故障与延误问题
10232乘客(问题)票价与效率性价比低问题
11285乘客(问题)管理服务混乱问题
12229乘客(问题)乘坐体验不舒适问题
13182乘客(问题)环境卫生与噪音问题

一目了然!

  • 正面评价集中在簇 1-5:舒适体验、贴心服务、高效出行、文化活动、暖心祝福
  • 负面问题集中在簇 6-13:空调温度、拥挤、设施不足、故障延误...

💡 批量处理技巧

1. 控制输入长度

每个簇可能有几百个要素,全部输入会超 token。我取前 20 个代表性要素作为输入:

def align_semantics(texts, max_samples=20):
    # 按频率排序,取前20个
    sample_texts = texts[:max_samples]
    prompt = f"""... 待分析文本:{sample_texts} ..."""

2. 低温度保证一致性

对齐任务需要稳定输出,temperature 设为 0.1:

data = {
    "model": "deepseek-chat",
    "messages": [{"role": "user", "content": prompt}],
    "temperature": 0.1,
    "max_tokens": 100
}

3. 异常处理

API 调用可能失败,要有 fallback:

try:
    response = requests.post(url, headers=headers, json=data, timeout=30)
    result = response.json()['choices'][0]['message']['content'].strip()
    return result
except Exception as e:
    print(f"API调用失败: {e}")
    return "【自动生成】" + texts[0][:50] + "..."

📐 完整代码

def align_semantics(texts):
    """使用DeepSeek API进行语义对齐"""
    prompt = f"""
    请将以下关于地铁服务的乘客反馈提炼为最核心的标准化表述,要求:
    1. 输出仅一条标准化表述
    2. 只保留最本质的需求/问题/感受
    3. 使用"乘客"作为主语
    4. 采用"乘客+核心诉求"的极简结构

    【输出规范】
    格式:严格遵循"乘客+[诉求类型]+[核心问题]"结构
    诉求类型:(需求)/(问题)/(评价)

    【典型范例】
    "乘客(需求)增加高峰班次"
    "乘客(问题)闸机故障率高"  
    "乘客(评价)赞赏暖心毕业祝福"

    待分析文本:
    {texts[:20]}  # 取前20个代表样本

    【最终输出】:
    """
    
    headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
    data = {
        "model": "deepseek-chat",
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.1,
        "max_tokens": 100
    }
    
    response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data, timeout=30)
    return response.json()['choices'][0]['message']['content'].strip()

💡 三条核心经验

1. 标准化格式是灵魂

"乘客(问题)空调温度不适" 比 "空调问题" 好在哪里?

  • 明确了主体(乘客视角)
  • 明确了性质(这是一个"问题",不是"评价"或"需求")
  • 运营方看到"(问题)"就知道需要解决,看到"(评价)"就知道是表扬

2. 输入样本要精选

不要把所有要素都扔给 LLM。取频次最高的前 20 个,既能代表簇的核心语义,又不会超 token。

3. 范例要覆盖不同类型

我给的范例覆盖了三种类型(需求/问题/评价),让模型知道每种类型应该怎么表述。

🔗 完整代码与项目

完整实现已开源在 GitHub:
👉 nanjing-metro-analysis/notebooks/02_semantic_alignment.ipynb

📮 写在最后

语义对齐是连接"机器聚类"和"人类理解"的桥梁。聚类算法只能把相似的放一起,但给这个簇起什么名字、如何标准化表述,还是需要 LLM 的语言能力。

下一篇是系列的最后一篇——《马斯洛理论重构地铁服务:挖掘 14,088 条文本背后的真实诉求》,我会把所有分析结果汇总,给出完整的业务洞察和运营建议。


本文是"南京地铁乘客需求分析"系列的第四篇。