客户情绪分析

更新时间:

基于客服聊天记录的情绪分析对提升企业服务质量具有重要意义。通过实时监测情绪波动,企业可以迅速识别高风险会话(如持续负面情绪),触发预警机制并优先分配高级客服介入,从而提升客户体验,降低流失风险。本文介绍如何在AnalyticDB PostgreSQL 7.0中使用pgml进行客户情绪分析。

前提条件

  • 已购买内核版本为v7.2.1.0及以上的AnalyticDB for PostgreSQL7.0版实例。

  • 实例的协调节点(Master):8CU及以上规格。

  • 实例的计算节点(Segment):8C32G及以上规格。

    说明
  • 实例资源类型为存储弹性模式。

  • 已经安装pgml插件。

    说明

    如果您已安装,在数据库的Schema列表中可以看到pgml。如未安装请提交工单,联系技术支持协助安装(需要重启实例)。如有卸载插件需求,也请提交工单联系技术支持协助卸载。

操作步骤

步骤一:创建业务表

在已安装pgml插件的目标数据库中,创建Schema和业务表并写入测试数据。

-- 创建SCHEMA
CREATE SCHEMA testschema;

-- 创建原始聊天记录表
CREATE TABLE testschema.chat_records (
    session_id VARCHAR(40),
    dialog_time TIMESTAMP,
    role VARCHAR(10),  -- 角色: customer/service
    dialog_text TEXT
);

-- 创建推理结果记录表
CREATE TABLE testschema.sentiment_raw_results (
   session_id character varying(40),
   raw_response text
);

-- 写入测试数据
INSERT INTO testschema.chat_records VALUES
('S001', '2024-05-01 09:30:00', 'customer', '你们的产品质量太差了!刚用三天就坏了!'),
('S001', '2024-05-01 09:31:00', 'service', '非常抱歉给您带来不便,我们可以安排免费换新'),
('S002', '2024-05-01 10:15:00', 'customer', '感谢客服耐心指导,问题已完美解决'),
('S003', '2024-05-01 11:20:00', 'customer', '我需要查询订单物流信息');

步骤二:使用模型进行单条数据推理

  1. 下载DeepSeek模型至协调节点(Master)。

    说明

    当前仅支持DeepSeek-R1-Distill-Qwen-7B模型。该模型不收费。

    SELECT pgml.download_built_in_model('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B');
  2. 使用该模型实现单条数据推理。

    SELECT 
        pgml.transform(
            task => '{
                "task": "text-generation",
                "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
                "load_in_8bit": false,
                "device_map": "auto"
            }'::JSONB,
            inputs => ARRAY[
                '请分析以下聊天记录中的客户情绪,正面表示用户很满意,负面表示有较大的流失风险,中性表示没有表现出情感倾向,不需要给出思考过程和理由,直接返回结果即可。
    例如:
    # 用户消息为:你好,我想咨询一下你们的套餐。
    # 情绪:中性
    
    现在根据下面的输入进行评分:
    # 用户消息为:'||'感谢客服耐心指导,问题已完美解决'||'
    # 情绪:</think>'
            ],
            args => '{
                "max_new_tokens": 10,
                "temperature": 0.1
            }'::JSONB
        ) AS response;

    参数说明

    参数名称

    描述

    子参数

    示例值

    task

    指定所使用的预训练模型以及任务类型。

    task:任务类型。

    task => '{
        "task": "text-generation",
        "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
        "load_in_8bit": false,
        "device_map": "auto"
    }'::JSONB

    model模型名称。

    load_in_8bit:与模型加载和量化(8bit量化)相关的参数。取值为:

    • false:禁用8-bit量化。

    • true:启用8-bit量化。

    device_map:与模型加载和设备分配相关的参数。auto表示框架自动将模型的不同部分分配到可用的设备上,以优化内存使用和计算效率。该设置非常适合处理大型模型或多设备场景。

    args

    将一组配置选项传递给某个逻辑单元(如函数、存储过程、API或模型)。

    max_new_tokens:限制模型在生成文本时的token数量。

    args => '{
        "max_new_tokens": 10,
        "temperature": 0.1
    }'::JSONB

    temperature:温度系数,控制生成随机性的参数。

    • 值越小,生成结果更加确定和稳定。适用于需要生成稳定、一致的结果的场景,例如问答系统、代码生成等。

    • 值越大,生成结果更加随机和多样化。适用于需要生成多样化、创造性的内容的场景,例如对话生成、故事创作等场景。

    inputs

    需要分类的文本。

    ARRAY['产品的质量很好']

步骤三:使用模型处理历史聊天记录

  1. 下载DeepSeek模型至计算节点(Segment)。

    SELECT pgml.download_built_in_model('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B') FROM gp_dist_random('gp_id');
  2. 处理历史聊天记录。

    WITH model_output AS (
    SELECT 
        session_id,
        pgml.transform(
            task => '{
                "task": "text-generation",
                "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
                "load_in_8bit": false,
                "device_map": "auto"
            }'::JSONB,
            inputs => ARRAY[
                '请分析以下聊天记录中的客户情绪,正面表示用户很满意,负面表示有较大的流失风险,中性表示没有表现出情感倾向,不需要给出思考过程和理由,直接返回结果即可。
    例如:
    # 用户消息为:你好,我想咨询一下你们的套餐。
    # 情绪:中性
    
    现在根据下面的输入进行评分:
    # 用户消息为:'|| string_agg(dialog_text, '; ')||'
    # 情绪:</think>'
            ],
            args => '{
                "max_new_tokens": 10,
                "temperature": 0.1
            }'::JSONB
        ) AS response
    FROM chat_records
    WHERE role = 'customer'  -- 仅分析客户发言
    GROUP BY session_id
    )
    
    INSERT INTO testschema.sentiment_raw_results
    SELECT 
        session_id,
        response->0->0->>'generated_text' AS raw_response
    FROM model_output;

    参数说明

    参数名称

    描述

    子参数

    示例值

    task

    指定所使用的预训练模型以及任务类型。

    task:任务类型。

    task => '{
        "task": "text-generation",
        "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
        "load_in_8bit": false,
        "device_map": "auto"
    }'::JSONB

    model模型名称。

    load_in_8bit:与模型加载和量化(8bit量化)相关的参数。取值为:

    • false:禁用8-bit量化。

    • true:启用8-bit量化。

    device_map:与模型加载和设备分配相关的参数。auto表示框架自动将模型的不同部分分配到可用的设备上,以优化内存使用和计算效率。该设置非常适合处理大型模型或多设备场景。

    args

    将一组配置选项传递给某个逻辑单元(如函数、存储过程、API或模型)。

    max_new_tokens:限制模型在生成文本时的token数量。

    args => '{
        "max_new_tokens": 10,
        "temperature": 0.1
    }'::JSONB

    temperature:温度系数,控制生成随机性的参数。

    • 值越小,生成结果更加确定和稳定。适用于需要生成稳定、一致的结果的场景,例如问答系统、代码生成等。

    • 值越大,生成结果更加随机和多样化。适用于需要生成多样化、创造性的内容的场景,例如对话生成、故事创作等场景。

    inputs

    需要分类的文本。

    ARRAY['产品的质量很好']

    查询结果。

    SELECT * FROM testschema.sentiment_raw_results limit 1;

    结果如下。

    session_id |                                                                        raw_response
    ------------+----------------------------------------------------------------------------------------------------------------------------------------------
     S002       | 请分析以下聊天记录中的客户情绪,正面表示用户很满意,负面表示有较大的流失风险,中性表示没有表现出情感倾向,不需要给出思考过程和理由,直接返回结果即可。例如
                | # 用户消息为:你好,我想咨询一下你们的套餐。                                                                                                                             
                | # 情绪:中性                                                                                                                                                  
                |                                                                                                                                                                                                                                                                                                        
                | 现在根据下面的输入进行评分:                                                                                                                                
                | # 用户消息为:                                                                                                                                              
                | 感谢客服耐心指导,问题已完美解决                                                                                                                           
                | # 情绪:</think>                                                                                                                       
                | 正面
    (1 row)

步骤四:转换为量化标签

转化为风险等级,以便企业后续跟进。

WITH sentiment_results AS(
    SELECT split_part(
        raw_response,
        '</think>',
        (length(raw_response) - length(replace(raw_response, '</think>', '')))/8 + 1
    ) AS raw_label,
    session_id
    FROM testschema.sentiment_raw_results
)
SELECT 
    r.session_id,
    r.dialog_time,
    r.dialog_text,
    CASE 
        WHEN s.raw_label~'负面' THEN '高风险(需优先跟进)'
        WHEN s.raw_label~'正面' THEN '低风险(归档观察)'
        ELSE '中风险(常规处理)'
    END AS risk_level
FROM testschema.chat_records r
JOIN sentiment_results s ON r.session_id = s.session_id
WHERE r.role = 'customer';

结果如下。

session_id	|    dialog_time	|    dialog_text	                |	risk_level		
----------------+-----------------------+-----------------------------------+-------------------
 S001		| 2024-05-01 09:30:00	| 你们的产品质量太差了!刚用三天就坏了!	| 高风险(需优先跟进)	
 S003		| 2024-05-01 11:20:00	| 我需要查询订单物流信息。		| 中风险(常规处理)	
 S002		| 2024-05-01 10:15:00	| 感谢客服耐心指导,问题已完美解决	| 低风险(归档观察)	
(3 rows)