RAG落地:第一个AI应用见效了

0 阅读6分钟

一、前言

为了更好的服务用户,提供个性化服务,帮助客户解决问题,结合当下火热的AI技术推出快捷导航功能。

其功能如下:

  • 语意理解:能够理解用户的自然语言输入,而不是单纯的关键词匹配搜索。
  • 个性化推荐:可以根据用户的偏好和历史行为来推荐相应的功能和信息,这使得用户可以更快地找到自己需要的功能,并更好地解决相应的问题。

image.png

什么是 RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是:

1、先“查资料”(从你的知识库中检索相关内容)

2、再“作答”(把检索结果交给大模型生成答案)

说白了:用户提问 -> 把问题转成向量去知识库检索 -> 找到最相关的若干片段

所以,RAG 的结构很像“搜索引擎 + 语言模型”的组合, 知识库构建是铺地基,检索模块就是“搜索引擎”部分。

1、知识库构建

背景:客服同学有维护一套面向客户的知识库,这块可以直接拿来使用。

  • 主要问答为主

  • 日常维护

在这个步骤可分为 3 个部分:

  1. 数据清洗:文档内容调整,其他不需要。
  2. 切片策略:无需再次切片,每个问答就是完整一个切片。
  3. Embedding选择:文档向量化。

名词解释:

名词说明
Embedding嵌入:把文本的意思嵌入向量里,用向量来表示文本的含义。音频、视频也行。
Vector向量:- 在数学中,向量是一种表示有大小和方向的量的工具。
  • 在这里,可以简单把向量理解为一种数据的编码方式,每个维度都可以被认为是一个特性或属性,这些特性或属性共同描述了一个数据点。 |

  • 为什么转为向量:因为转向量后,这样我们就可以通过一些算法来计算文本的相似程度「比如余弦相似度(Cosine Similarity)、欧氏距离(Euclidean Distance)等等。

  • 如何把文本转化成向量:转化的过程其实就是文本特征提取,要用专业名词就是词嵌入。这个过程需要特定的模型「比如词袋模型、TF-IDF等」。

image.png

2、检索模块(Retrieval)

目标:在知识库中,快速准确地找到相关的切片。

对应检索 pipeline:

image.png

  1. Query 向量化:将用户的问题,变成可计算的向量。

  2. 召回阶段:快速找到Top K,采用 混合检索(Hybrid Search)

    1. 向量召回(Dense Retrieval):基于Embedding的语义相似度检索。
    2. 关键词召回(Sparse Retrieval):基于传统搜索技术,如BM25或倒排索引。
  3. 精排阶段:会把 Query 和候选文本一起输入,逐条计算相关度分数。取 Top K1,再交给 LLM 进行生成。

  4. 结果过滤:检查过滤,敏感词 / 相同片段去重。

混合检索(Hybrid Search)

随着数据量的增加,会存在语义相似度不可解释的问题,而且不一定会随着关键词做语义相似度的完全跟随。

只靠向量语义检索不够稳,需要“关键词检索 + 语义检索”组合起来用。

  • 语义检索像“凭感觉找意思接近的内容”,很聪明,但有时说不清“为什么命中这条”。
  • 当数据越来越多时,这种“感觉”会变得不稳定:你明明输入了某个关键词,它不一定严格跟着这个词去找。
  • 所以要加上关键词检索这条“硬规则”链路,先把可能相关的结果尽量召回,再用语义相似度做二次排序(精排),把最像的放前面。

采用关键词召回方案:

  • 1、关键词命中召回

    • 用户问到的词,文档里直接出现了,就优先拉进候选集合。
    • 例:搜“发票抬头”,包含这个词的文档先召回。
  • 2、近义词逻辑

    • 用户和文档用词不一致,但意思相近也要能找到。
    • 例:“报销凭证”≈“发票”;“退款”≈“退费”。
  • 3、pinyin逻辑

    • 处理中文拼音输入、错别字、输入法习惯。
    • 例:用户输“fapiao”,也能召回“发票”。
  • 4、ngram召回

    • 把词拆成连续片段匹配,提升对部分匹配、错拼、黏连词的鲁棒性。
    • 例:“增值税专用发票”拆成若干片段,输入不完整时也能匹配到。

一句话总结:

  • 召回阶段要“宁可多抓一些”(关键词+近义词+pinyin+ngram)
  • 排序阶段再“优中选优”(语义相似度精排)
    这样效果通常比“只用向量”更稳定、更可解释。

二、工程落地

组件模块划分:

  • 向量数据库采用:Elasticsearch。
  • 知识库构建:每日定时获取文档,文档向量化,存储。
  • 检索服务:交互 chatgpt、ES。

查询交互时序图如下:

image.png

ES 索引配置如图:

image.png

 PUT /vector_query
    {
        "settings":{
            "number_of_shards":1,
            "number_of_replicas":1
        },
        "properties": {
          "category": {
            "type": "keyword"
          },
          "main_path": {
            "type": "keyword"
          },
          "sub_path": {
            "type": "keyword"
          },
          "title": {
            "type": "text"
          },
          "doc": {
            "type": "text"
          },
          "title_vector": {
            "type": "dense_vector",
            "dims": 1536
          },
          "doc_vector": {
            "type": "dense_vector",
            "dims": 1536
          }
        }
    }

检索 demo如图:

image.png

def get_sim_doc(inp, get_emb=get_emb, es_mpt_index=es_mpt_index, topk=10):
        logger.info('get_sim_doc-' + inp)
        inp_emb = get_emb(inp)
        logger.info('get_sim_doc-' + 'emb success!')
        data = {
            "_source": {
                "excludes": ["*_vector"]
            },
            "size": topk,
            "query": {
                "script_score": {
                    "query": {
                        "match_all": {}
                    },
                    "script": {
                        "source": "if (cosineSimilarity(params.queryVector, 'title_vector')<cosineSimilarity(params.queryVector, 'doc_vector')) {return cosineSimilarity(params.queryVector, 'doc_vector')+1}return cosineSimilarity(params.queryVector, 'title_vector')+1",
                        "params": {
                            "queryVector": inp_emb
                        }
                    }
                }
            }
        }
     
        url = f'{es_host}/{es_mpt_index}/_search'
        response = requests.post(url, headers=headers, json=data, auth=auth)
        # print(response)
        hits = response.json()['hits']
        # print(json.dumps(data, ensure_ascii=False))
        return hits

1、向量模型接入

有两种不同的向量模型接入方案:

  1. ada 方案调用:通常指调用 OpenAI 的 embedding(历史上常叫 ada,如 text-embedding-ada-002,现在更多用 text-embedding-3-*)。
  2. bge 方案调用:指调用 BGE 系列 embedding(BAAI 开源模型,如 bge-large-zhbge-m3),一般是你自部署或走第三方推理服务。

接入的3个模型对比:

维度BGE文心一言OpenAI
私有化部署强(可完全自建)中(看产品形态)弱(通常云API)
中文检索中-强
生成能力中(看搭配的LLM)
工程复杂度低-中低-中
成本可控性强(规模化后)中-弱

其他因素:

  1. 法务要求:优先国内模型
  2. 稳定性:考虑openai服务的不确定性,时常异常,暂时未做压测;(2023年12月份)

三、应用

背景:客服侧反馈店铺托管咨询量上月已达到 2300+条,4月7号单天咨询已经达到260+条,已严重影响其他正常客户的进线咨询,部分客户需要等待30分钟-1个小时后才能真正进入到人工接待,非常影响客户体验。

客户搜索店铺托管相关的关键词,跳出如何开通。

客户选择如何开通之后 展示:您好,您可点击申请立即开通(蓝色字体)按钮进行开通。

流程如下:

  1. 重复开通:需要判断是否已经开通,已开通提示已经开通,无需重复开通
  2. KYC异常:客户点击【立即开通】校验KYC状态,未完成KYC引导完成KYC
  3. 开通成功:客户点击【立即开通】校验 1 和 2 通过后,提示开通成功