0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

利用大模型服务一线小哥的探索与实践

京东云 来源:jf_75140285 作者:jf_75140285 2024-06-17 14:59 次阅读

一、小哥作业+大模型

2022年OpenAI基于GPT推出了聊天机器人ChatGPT,带来了非常惊艳的语言理解、内容生成、知识推理等能力,能够准确理解人的语言、意图,并能够回答出清晰、完整的内容,让人很难分辨出沟通交流的是人类还是机器人。

大模型会尝试基于已有的内容,生成内容的延续。基于预训练阶段加入的海量文章、电子图书、网页内容等等,大模型给出最接近我们期望的内容。比如我们提供的内容是“北京是...”,大模型扫描海量内容进行排名,为了让内容更有创造力,大模型使用了巫术,一般采用基于可配置参数(top K, top P, Temperature) 的概率随机采样来选择单词,而不是总采用排名最高的单词。通过延续生成了“北京是一座充满活力的城市”。人类反馈强化学习(RLHF)即基于人类反馈对大语言模型进行强化学习,通过人工标注来构建奖惩网络,强化学习基于奖惩网络对模型进行迭代优化,改善生成内容的质量。

快递快运终端系统是快递小哥、快运司机、网点管理者日常使用的系统,是物流作业人员最多、作业流程最末端、服务形态最多元的系统。大模型带来了新的方法来解决小哥提出的问题、遇到的异常、需要的支持,并提供帮助网点管理者进行运营和经营管理的工具。

提升小哥作业效率,就需要了解小哥日常工作中有哪些作业动作,然后根据作业动作的特点,来分析大模型有什么样的机会来实现效率提升。通过调研和分析,小哥有143项作业动作,可分类为:揽收、派送、站内、辅助、客户服务五大类,其中22项动作是系统外的线下动作,其他动作中有69项被认为有大模型结合的机会。在69项中我们选取了小哥揽收信息录入、外呼、发短信、查询运单信息、聚合查询、知识问答、精准提示等场景,通过大模型与大数据、GIS、语音等技术的结合,为小哥提供高效、易用的作业工具。

wKgaomZv3rOABS46AAC06867OsU472.png

二、智能操作

小哥日常作业中,会频繁给客户打电话、发短信。出于客户个人隐私安全的考虑,面单中隐藏了电话,所以外呼前需要小哥一次次在系统中查找电话,经常是扫单号、在详情页点击外呼按钮、拨打电话等一系列动作。通过小哥语音,大模型可以帮助我们分析小哥的意图,识别出拨打电话,就可以通过语音中提到的运单尾号、地址等特征完成外呼。

基于常规算法的解决方式是多个小模型组合成pipline,各小模型分别进行标注和训练,pipline存在误差传递问题。使用大模型后,不需要进行标记和训练,可以直接投入使用,减少了算法开发的难度和周期,提升研发交付效率。在接收到小哥语音输入后,语音识别(ASR)将语音转化为文字,文字通过大模型意图识别、信息抽取等方式生成指令,并调用系统API实现作业功能。

小哥智能助手中智能操作的实现方法如下:

wKgZomZv3rWAfWx3AAHkhOUzIOU306.jpg

在小哥发短信时,需要查找电话,在短信界面编辑文字,通过语音+大模型,识别小哥需要给客户发短信,并通过大模型对短信内容进行再加工,完成正式的短信编写。

在填写揽收信息时,小哥需要频繁切换电子称、卷尺、工业机来完成称重量方和信息录入等作业动作,同时揽收还需要填写托寄物、时效产品、增值服务等内容,如果通过语音+大模型,就可以减少工业机的多次输入,会直接识别语音,分析出小哥的输入意图和内容,将信息正确填写。

小哥查询信息,也可以通过语音输入,大模型识别意图,进行结果的反馈。如下是通过大模型实现的意图识别示例:

wKgaomZv3rWARZKYAAYH5fnpcYg773.jpg

wKgZomZv3reAE6DwAAboQyjHxvg085.jpg

三、智能问答

业务快速发展的同时,也对小哥作业提出了非常高的要求,据不完全统计,仅终端相关文件就有915个,如货物处理规程、安全操作标准、KA客户服务要求等等。对于小哥来说,记忆并掌握这么多业务要求无疑是一项巨大的挑战,小哥对标准作业流程或规范了解不全面,会影响服务质量,也会影响一线作业效率,造成时间和成本浪费。

小哥不了解流程、规则或者遇到运营问题,目前通过问站长/站助/其他小哥、提报IT工单、联系终端小秘等方式解决,但是被咨询人也会因为对业务规则、流程了解不全面而无法给出正确的回答。大模型出现后能够更清晰的理解小哥的问题和意图,提供更加简洁的回答,提高回答的准确率,降低了小哥的理解成本。

通过Prompt+检索增强生成(RAG)实现了第一阶段的智能问答。之所以需要检索增强生成是因为大模型目前存在幻觉、知识过时等问题,RAG实现从外部知识库中检索相关信息进行回答,提高答案的准确性。

wKgaomZv3riAW04IAAEL5DMEuEM184.png

小哥智能助手中智能问答的实现方法如下:

wKgZomZv3rmAT1RYAAGEspNa1AE476.jpg

【内容提取】业务文档格式多样,也包含各种内容元素,比如包含表格的文档,只进行文字提取,无法保证内容的结构性、可读性,输入给大模型后无法理解,导致回答不准确。所以我们对文件内容进行提取时,将文件中的表格转换为语义化的内容,保证知识的可读性。如下是业务文档中的表格内容:

wKgaomZv3rqANGIDAAG73uwCwZ0381.png

wKgZomZv3ryADQFvAAR_ywamEYE333.png

【内容切分】大模型能够找到的相关知识的质量和数量决定了回答的正确性和完整性,但是由于大模型token的数量限制,我们必须将文档内容切分。最初我们设置300个字符为一个知识块进行切分,从回答的效果上看,有很多问题回答的内容不完整,因为单纯的按照字数切分会破坏内容的完整性,需要引入段落切分,保持段落完整性。

wKgaomZv3r2ASdUmAAk0fWQ2ABc968.png

具体实现方法如下:

a. 内容提取

第一版采用了DocumentLoaderUtil直接提取文本,将文本信息存入txt文件,具体实现方式如下:

from src.document_loader.document_loader import DocumentLoaderUtil
processor = DocumentLoaderUtil(file_path=path_ori, pic_save_dir=dir_save_picture)

texts = processor.load()
texts = json.dumps(texts, ensure_ascii=False, indent=4)

with open(os.path.join(dir_save_text, f"{os.path.basename(path_ori)}.txt"), "w") as f:
    f.write(texts)

优化后处理DOCX文件:

1.读取文档信息时,遇到表格,将表格单独存储到excel中,并在文本中使用特殊占位符标注表格位置;

2.结合大模型对表格进行语义化处理,使表格信息转化成语义化文本;

3.根据特殊占位符将语义化文本回填至文档对应位置;

# 提取word中的表格
def extract_tables_to_excel(docx_path, excel_result_path):
    doc = Document(docx_path)
    docx_name = os.path.splitext(os.path.basename(docx_path))[0]
    folder_path = os.path.join(excel_result_path, docx_name)

    if not os.path.exists(folder_path):
        os.makedirs(folder_path)
    table_count = 0
    for table in doc.tables:
        table_count += 1
        data = [[cell.text for cell in row.cells] for row in table.rows]
        df = pd.DataFrame(data)
        # 保存DataFrame到Excel文件
        excel_path = os.path.join(folder_path, f"【表格{table_count}】.xlsx")
        df.to_excel(excel_path, index=False, header=False)
    return folder_path

# 根据占位符插入表格内容
def replace_marker_in_txt(file_path, marker, replacement_text):
    # 读取原始文件内容
    with open(file_path, 'r+', encoding='utf-8') as file:
        content = file.read()
        if replacement_text is None:
            replacement_text = ''
        # 替换特定标记
        content = content.replace(marker, replacement_text)
        file.seek(0) 
        file.write(content) 
        file.truncate()

# txt中插入表格
def insertTable(folder_path, txt_path):
    for filename in os.listdir(folder_path):
        filepath = os.path.join(folder_path, filename)
        filename_without_extension, _ = os.path.splitext(filename)
        # 处理表格为语义化文本
        result = excel_to_txt_single(filepath)
        # 占位符替换处理后的文本
        replace_marker_in_txt(txt_path, filename_without_extension, result)

优化后处理PDF文件:

1.读取文档信息提取表格,结合大模型对表格进行语义化处理,使表格信息转化成语义化文本;

2.寻找表格内容并替换内容;

# 处理pdf
def process_pdf(file_path, file_name, output_directory, save_directory, txt_file):
    individual_file_names = save_pdf_tables_to_excel(file_path, file_name, output_directory)
    content = DocumentLoaderUtil(file_path, save_directory).load()
    content = [doc['page_content'] for doc in content]
    with open(txt_file, 'w', encoding='utf-8') as f:
        for line in content:
            f.write(line + 'n')
    replace_similar_module_in_txt(individual_file_names, txt_file, file_path)
# 特殊pdf二次处理
def handle_exception(extension, file_path, file_name, output_directory, save_directory):
    try:
        if extension == '.pdf':
            individual_file_names = save_pdf_tables_to_excel(file_path, file_name, output_directory)
            text, txt_file = convert_pdf_to_txt(file_path, os.path.join(save_directory, 'txt'))
        else:
            return
        with open(txt_file, 'w', encoding='utf-8') as output_file:
            output_file.write(text)
        replace_similar_module_in_txt(individual_file_names, txt_file, file_path)

    except FileNotFoundError as e:
        with open('error.md', 'a') as file:
            file.write(f"文件未找到错误:{file_path}n")
    except Exception as e:
        with open('error.md', 'a') as file:
            file.write(f"handle_exception处理异常时发生错误:{file_path}n")

# 查找表格位置并替换为语义化内容
def replace_similar_module_in_txt(individual_file_names, txt_file, file_path):    
    # 读取文本文件的原始内容
    with open(txt_file, 'r', encoding='utf-8') as file:
        txt_content = file.read()
    
    for excel_path in individual_file_names:
        excel_content = read_excel_content(excel_path)
        # 查找最相似的片段
        most_similar_part = find_most_similar_part(txt_content, excel_content, threshold=0.02)
        if most_similar_part:
            # 替换成语义化文本
            replacement_text = excel_to_txt_single(excel_path)
            txt_content = safe_replace(txt_content, most_similar_part, replacement_text)
        else:
            # 找不到时 将内容追加到文档后
            replacement_text = excel_to_txt_single(excel_path)
            txt_content += replacement_text

    with open(txt_file, 'w', encoding='utf-8') as file:
        file.write(txt_content)

b. 内容切分

第一版按照字符数切分,固定300字符+15%的滑动窗口。核心代码如下:

from src.text_splitter.text_splitter import TextSplitterUtil

splitter_name = "RecursiveCharacterTextSplitter"
splitter_args = {
    "chunk_size": 300,
    "chunk_overlap": round(300 * 0.15),
    "length_function": len,
}

splitter = TextSplitterUtil(splitter_name, splitter_args)

with open(os.path.join(dir_save_text, f"{os.path.basename(path_ori)}.txt")) as f:
    texts = json.load(f)

texts_splitted = splitter.create_documents(
    texts=[t["page_content"] for t in texts],
    metadatas=[{"source": f"{path_ori}_{ti}"} for ti, t in enumerate(texts)],
)
print(texts_splitted)

优化后按照段落+500字符+10%的重叠进行切分。经过测试回归发现,效果明显提升。

import os
import json
import re
import csv

# 按优先级顺序存储正则表达式
def find_all_matches(doc, patterns):
    last_end = 0
    matches = []   
    # 搜索所有的匹配项
    for pattern in patterns:
        for match in pattern.finditer(doc):
            start, end = match.span()
            # 如果当前匹配块前有未匹配的内容,则将其作为单独的匹配块
            if start > last_end:
                matches.append(doc[last_end:start])
            matches.append(match.group())
            last_end = end  
    if last_end < len(doc):
        matches.append(doc[last_end:])
    
    return matches

def trim_regex_title(path_ori):
    with open(path_ori, 'r', encoding='utf-8') as file:
        document = file.read()

    # 使用非贪婪匹配 .*? 来捕获标题后的内容,直到遇到下一个标题或文档末尾
    # 初始化 matches 为空列表,用于存储找到的匹配项
    # 按优先级顺序存储正则表达式
    patterns = [
        re.compile(r'((?:一、|二、|三、|四、|五、|六、|七、|八、|九、|十、|d+.)[^n]+)([sS]*?)(?=n(?:一、|二、|三、|四、|五、|六、|七、|八、|九、|十、|d+.)[^n]+|$)'),
        re.compile(r'(n.+?)(?=n.+|$)'),
        re.compile(r'(?s)(nd+.d+s+.*?)(?=nd+.d+s+|$)')
    ]

    matches = find_all_matches(document, patterns)
    page_contents = []
    for match in matches:
        section_content = match.strip()
        page_contents.append({
            'page_content': section_content,
            'metadata': {
                'source': path_ori,
            },
        })
    # 组装成500字
    # 创建一个空列表用于存储处理后的page_checks
    page_checks = []

    # 用于累积不足500字符的内容
    accumulated_content = ""
    for page in page_contents:
        page_content = page['page_content']
        # 如果当前行内容加上累积的内容超过500字符,则需要分割
        if len(accumulated_content) + len(page_content) > 500:
            # 如果之前有累积的内容,先处理
            if accumulated_content:
                page_check_dict = {
                    "page_content": accumulated_content,
                    "metadata": {"source": path_ori}
                }
                page_checks.append(page_check_dict)
                accumulated_content = "" 

            # 处理当前行的内容
            start_index = 0
            while start_index < len(page_content):
                end_index = min(start_index + 500, len(page_content))
                page_check_dict = {
                    "page_content": page_content[start_index:end_index],
                    "metadata": {"source": path_ori}
                }
                page_checks.append(page_check_dict)
                # 更新start_index以便获取下一个500字符的片段,与前一个片段有50字符重叠
                start_index += 450
        else:
            # 如果当前累积内容与新行内容总和不超过500字符 继续累积内容
            if len(accumulated_content) + len(page_content) < 500:
                accumulated_content += page_content
            else:
                # 累积内容已足够,创建一个page_check
                page_check_dict = {
                    "page_content": accumulated_content,
                    "metadata": {"source": path_ori}
                }
                page_checks.append(page_check_dict)
                accumulated_content = page_content

    # 处理文件末尾的累积内容
    if accumulated_content:
        page_check_dict = {
            "page_content": accumulated_content,
            "metadata": {"source": path_ori}
        }
        page_checks.append(page_check_dict)
    return page_checks

c. 向量化 Embedding

用户的问题往往非常口语化,而文档和知识往往都是非常的专业和正式。比如用户的问题是:“我去年已经离职了,现在自己干,如何交公积金?”。从文档中需要检索出“灵活就业人员”办理公积金的材料和流程。内容检索只能进行精确匹配,对于近义词、语义关联词的检索效果较差。文本向量化后,搜索就可以通过计算词语之间的相似度,实现对近义词和语义关联词的模糊匹配,从而扩大了搜索的覆盖范围并提高了准确性。Embedding 就是将这些离散的文本内容转换成连续的向量。我们将向量存储到Vearch库中,选择相似度top9的向量对应的内容文本输入给大模型,通过Prompt进行回答。

from src.embedding.get_embedding import get_openai_embedding

model_key = "xxxx"
model_name = "text-embedding-ada-002-2"

texts_embedding = [
    get_openai_embedding(
        text=t.page_content, model_name=model_name, model_key=model_key
    )
    for t in texts_splitted
]

d. 内容管理

我们为向量创建索引,以便于检索和更新,同时将各阶段产物包括源文件、切分脚本、切分文本块、向量嵌入脚本、向量存储通过oss进行管理,并建立映射表。当业务知识进行更新时,可以对向量库中的内容进行更新替换。

wKgZomZv3r-AK9iIAAZfWdR09qY517.png

通过持续优化智能问答准确率90%,目前已接入小哥App、京ME、站长工作台、京象App等,功能如下:

wKgaomZv3sGAYowjAAl7B9t1LKQ481.png

四、智能提示

小哥作业流程规范,以及履约中的时效预测和提醒等等,都可以使用大模型将复杂的业务文档和流程规范转化为小哥容易理解和执行的操作提示,在任务下发、临期提醒方面也可以发挥大模型的理解和总结能力,使小哥关注到最需要关注的信息,帮助小哥做进一步的作业决策。比如KA商家对揽收打包方式、交接方式有各自不同的定制化需求,如果通过小哥记忆或者查资料的方式了解揽收打包要求,非常麻烦且耗时,利用大模型总结KA商家操作要求,通过语音合成(TTS)引导小哥按照客户要求作业,能够提升业务的履约质量。

wKgaomZv3sKAVHQLAAXrmKkyC8I703.jpg



小哥智能助手中智能提示的实现方法,以售后取件单下发为例:

wKgZomZv3sOAPYWMAAHyGujQTDk216.jpg

提示的差异对比如下:

wKgaomZv3sSAAxcdAARIUrHdG6E392.jpg

五、智能体

以GPTs为代表的大模型智能体带给了人们非常震撼的功能效果,引起的社会关注度远超之前任何一项技术的出现。但是OpenAI也坦言在智能体这个领域,自己并没有比其他公司掌握的更多,这也是目前很多科技公司在同一起跑线上奋力奔跑的机遇。

An agent is anything that can be viewed as perceiving its environment through sensors and acting upon that environment through actuators.

—— Stuart J. Russell and Peter Norvig

在智能操作、问答、提示的实践过程中,我们积累了模型、Prompt、知识库、微调等相关经验,但是在模型编排、领域模型训练、安全性等方面需要进一步学习和应用。同时我们也在探索终端智能体对业务异常分析、定位和解决的能力。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 机器人
    +关注

    关注

    210

    文章

    28204

    浏览量

    206520
  • GPT
    GPT
    +关注

    关注

    0

    文章

    351

    浏览量

    15313
  • OpenAI
    +关注

    关注

    9

    文章

    1043

    浏览量

    6407
  • 大模型
    +关注

    关注

    2

    文章

    2328

    浏览量

    2481
收藏 人收藏

    评论

    相关推荐

    神话游戏热浪推动文化输出,第一线全栈云网安服务助力游戏企业加速全球化部署

    工程师采用第一线SD-WAN+SASE 访问基础云数据,可获得诸多优势。第一线SD-WAN 智能整合不同网络链路,可根据链路质量,选择最优网络方案,确保访问平稳流畅。第一线SASE则为企业工程师访问基础云,提供全方位安全防护,保
    的头像 发表于 08-23 17:08 208次阅读
    神话游戏热浪推动文化输出,第<b class='flag-5'>一线</b>全栈云网安<b class='flag-5'>服务</b>助力游戏企业加速全球化部署

    工程智能发展之路(二):利用模型打造新代工业智能的数字底座

    笔者按: 2024,行业“GPT时刻”来临。笔者看到,在汇聚人类顶尖智慧与精湛工艺的半导体行业,以智现未来为代表的工业软件供应商,正发挥着其深耕行业数十年的数据积淀、技术储备和深厚的一线服务经验,以
    的头像 发表于 05-24 15:06 435次阅读
    工程智能发展之路(二):<b class='flag-5'>利用</b>大<b class='flag-5'>模型</b>打造新<b class='flag-5'>一</b>代工业智能的数字底座

    大语言模型:原理与工程实践+初识2

    系列变革。 大语言模型是深度学习的应用之,可以认为,这些模型的目标是模拟人类交流,为了理解和生成人类语言。为此,模型需要在大量文本数据
    发表于 05-13 00:09

    【大语言模型:原理与工程实践】大语言模型的应用

    ,它通过抽象思考和逻辑推理,协助我们应对复杂的决策。 相应地,我们设计了两类任务来检验大语言模型的能力。类是感性的、无需理性能力的任务,类似于人类的系统1,如情感分析和抽取式问答等。大语言模型在这
    发表于 05-07 17:21

    【大语言模型:原理与工程实践】大语言模型的评测

    安全性的评测则关注模型在强化学习阶段的表现。行业模型的评测则针对特定行业的能力,如金融和法律等领域。整体能力的评测从宏观角度评估模型作为个通用人工智能的综合能力。这些评测方法和基准的
    发表于 05-07 17:12

    【大语言模型:原理与工程实践探索《大语言模型原理与工程实践》2.0

    《大语言模型“原理与工程实践”》是关于大语言模型内在机理和应用实践次深入探索。作者不仅深入讨
    发表于 05-07 10:30

    【大语言模型:原理与工程实践】大语言模型的基础技术

    概率推断,利用共现矩阵学习每个词的主题分布,进而将其作为词的表示向量。在大规模语料库中进行模型训练,使语义相似的词具有相似的主题分布。然而,这类方法存在个问题,即模型
    发表于 05-05 12:17

    【大语言模型:原理与工程实践】揭开大语言模型的面纱

    关系,从而在各种任务中表现出色。Transformer架构的推出,标志着语言模型技术的重大突破。它摒弃了传统的递归方式,利用自注意力机制捕捉序列中的依赖关系。这创新极大地提高了模型
    发表于 05-04 23:55

    【大语言模型:原理与工程实践探索《大语言模型原理与工程实践

    的未来发展方向进行了展望,包括跨领域、跨模态和自动提示生成能力方向,为读者提供了对未来技术发展的深刻见解。《大语言模型原理与工程实践》是本内容丰富、深入浅出的技术书籍。它不仅为读者提供了大语言
    发表于 04-30 15:35

    名单公布!【书籍评测活动NO.31】大语言模型:原理与工程实践

    方法多被保密,难以获得实际操作的指导。为了填补这空白,我们历经年的实践探索,决定分享我们的经验和成果,旨在为大语言模型的初学者和
    发表于 03-18 15:49

    名单公布!【书籍评测活动NO.30】大规模语言模型:从理论到实践

    ,在大模型实践和理论研究的过程中,历时8个月完成 《大规模语言模型:从理论到实践书的撰写。希望这本书能够帮助读者快速入门大
    发表于 03-11 15:16

    应用大模型提升研发效率的实践探索

    对于模型训练,我们可以采用 3D 并行训练的方式来实现。将模型参数和梯度张量划分为多个分区,分配到不同 GPU 卡上进行计算。每张卡负责自己分区的梯度和参数更新工作,间隔时同步到其他卡上。这样可以很好地利用更多计算资源,降低单卡
    的头像 发表于 02-22 11:47 603次阅读
    应用大<b class='flag-5'>模型</b>提升研发效率的<b class='flag-5'>实践</b>与<b class='flag-5'>探索</b>

    Dynamics 365 Field Service:为每位一线员工配备随身智能助手

    Microsoft Dynamics 365 Field Service 利用互联现场服务,为企业提供自动化、个性化的运营方式,让一线技术人员的工作更轻松,也让服务运营得以优化,为企业
    的头像 发表于 12-22 08:10 414次阅读
    Dynamics 365 Field Service:为每位<b class='flag-5'>一线</b>员工配备随身智能助手

    芯知识 | 语音芯片支持一线串口和两线串口的作用与应用优势

    随着科技的不断进步,语音芯片作为现代电子产品中的核心组件,其功能和性能也在不断提升。其中,语音芯片支持一线串口和两线串口的功能,在实际应用中具有重要的作用和优势。首先,让我们了解一线串口和两线
    的头像 发表于 12-20 08:39 684次阅读
    芯知识 | 语音芯片支持<b class='flag-5'>一线</b>串口和两<b class='flag-5'>线</b>串口的作用与应用优势

    STM32用一线式驱动SD NAND,SDIO的一线式驱动

    SDIO(Secure Digital Input/Output)是种用于在嵌入式系统中连接外部设备的标准接口。在SDIO标准中,一线式和四线式是指SDIO接口的不同工作模式。
    的头像 发表于 12-19 14:14 858次阅读
    STM32用<b class='flag-5'>一线</b>式驱动SD NAND,SDIO的<b class='flag-5'>一线</b>式驱动