基于gpt4all的企业内部知识问答服务应用搭建

文章目录

  • 痛点
  • 项目缘起
  • 技术选型
    • fine-tuning
    • few shot prompt engineering
    • 选定方案的特征描述
  • 模型赛马
  • gpt4all调优
    • 部署时踩坑
      • python3.9 header缺失 -- 安装下缺失的就行
      • 运行时参数调优
  • 代码分析
    • 项目代码
    • 库代码
  • 效果展示
    • 例子1
    • 例子2
  • 附录:所用的公司内部API文档例子:

痛点

不太熟悉互联网企业的人士,往往将其想象成超现代风格的内部流程,一切都自动化,达到科幻电影的程度;但是真实在行业中摸爬滚打过几年的人士,会体会到流程自动化是一个过程,现实中由于工期紧张、历史习惯、实施成本等因素,流程中保留了大量手工操作。
以Shopee的DoD(Dev on duty)值班流程为例子,系统微服务的设计风格,每个开发组负责维护其中一个模块,可能用户感知到的一个页面,可能对应很多后台模块(背后是多个开发组)。作为一个跨国公司,Shopee的业务分散在很多个国家,不是每个国家的运营人员对这种分工都非常熟悉,往往first call会搞错,虽然我们规定了first call的组负责转发支持请求,但是这样往往耽误时间,特别是深夜值班,得把人从睡梦中叫醒后发现又不是该人负责;又或是大促期间的值班,这样的转发也耗费时间,耽误一分钟就损失XXXXXX元钱。

项目缘起

为了解决这个问题,之前我们靠人工的办法,编写了一个长达200页的ppt,详细介绍了DoD的流程和分工。但是问题是,这套ppt要讲解也是要成本的,而且效果不好,特别是还要涉及跨境的团队,还有翻译、培训组织等一堆的事情。
今年随着chatgpt的流行,我们开始考虑使用人工智能的方式回答一线员工发现问题的first call,减轻ppt培训成本,减少失误率,且能够自动进行语言的翻译。也就是如下几种能力,最终自动找到对应的负责团队:

  • 跨语言能力
  • 模糊语义理解能力
  • 推理能力
    考虑到企业信息安全,根据Shopee的指引,这套系统必须部署在企业内部。

技术选型

要实现如上系统,考虑有两套技术方案:

fine-tuning

用白话说是在chatgpt等巨人的肩膀上,采用标准模型,加上自己数据,自己炼丹。

大模型训练结束后,参数固定,模型内部蕴含的知识也固定。想要让模型增加知识,可以通过微调改变模型参数实现。
微调是以预训练LLM为基底,预训练模型是在大量通用数据集上训练,微调则是在少量特定领域数据集上训练,通过较低的成本获取特定领域的知识。
具体微调流程为:构建微调数据集 → SFT(supervised fine tuning,有监督微调) → RLHF(reinforcement learning & human feedback)
该方案优点是模型对领域知识理解更正确,效果更好;缺点是需要开源模型,需要收集数据并进行加工,微调大模型也需要较高的显卡成本,总体来说成本较高,且微调后模型推理效果不能保证。

few shot prompt engineering

用白话说就是直接chatgpt等LLM本身,但是其缺乏企业内部知识(比如那个200页的ppt),怎么办呢?就是采用langchain等编程手段,在对话上下文中提供信息。

在openAI的gpt-2论文中,就定义LLM本质上few-shot/zero-shot learning,具备很强的泛化能力。
只需要在提示词(prompt)中清楚地阐明上下文,即使训练集中不包含相关知识,模型也能对上下文正确理解和分析。
具体流程为: 构建外部知识库 → 相关知识匹配 → few shot prompt构建 → LLM推理
该方案优点是不需要训练,拓展性强,可使用现有大模型产品,如chatgpt、new bing等;缺点是LLM对外部知识理解较差,构建知识库需要一定成本等。

两个方案各有优缺点,不过方案一更费钱,那时的Shopee,节约成本是压倒一切的纲领,所以经过技术评审,毫无悬念采用了方案二。所以如果有新人问我啥是技术选型,我看要提醒一下他/她别被这个名字给骗了,很多时候决定选型的是技术之外的因素。

在这里插入图片描述

选定方案的特征描述

LLM是无状态的,这个一个模型文件大概10G不到,可以只读入container。理论上虽然消耗cpu,业务高峰期可以横向扩展container保证响应时间。
基本上是一个后端应用,采用python或者golang搭建,使用库文件的方式在本地调用大语言模型LLM,开放http接口的api给调用方使用
新建应用,代码提交到gitlab,采用CICD进行部署

模型赛马

方案二确定下来之后,到底该用哪个LLM呢,这里才到了真正技术发挥决策作用的地方,我们成立了一个小组,招募了对AI和LLM有兴趣的同事,每个人带着自己看好的LLM,分配给每个人计算资源,最后用数据说话,看哪个LLM的性能更好,消耗更少
各自分头选定模型(gpt4all, chatGLM, FLAN T-5, Alpaca),然后用数据集合测试,看看实际性能

姓名模型特点资料
zezhouchatgpt2(后来发现不行);gpt4all offlinefree, local run, No GPU requiredhttps://gpt4all.io/index.html
https://github.com/nomic-ai/gpt4all
jinhaochatGLMhttps://github.com/imClumsyPanda/langchain-ChatGLM/blob/master/docs/INSTALL.md
zouxuan YapFLAN T-5https://medium.com/@koki_noda/try-language-models-with-python-google-ais-flan-t5-ba72318d3be6
Yunyuan YuAlpacahttps://beebom.com/how-run-chatgpt-like-language-model-pc-offline/
最后经过比较,决定采用gpt4all

gpt4all调优

这部分会比较技术细节一些,涉及部署时的踩坑,和运行时调优。如果产品的同事要只看效果可以直接跳到最后一部分。

部署时踩坑

最早用chatgpt2的时候,发现始终安装不了,所以最终才决定用gpt4all。其原因是python版本问题
chatgpt-2是n年前的项目,所以用的tensorflow都是老版本的1.15,而我现在机器上是3.11了,只能安装最新的tensorflow结果报错
所以python环境很重要,各位实验时,可以用pyenv在自己mac机器上,安装好py2到py3的各个版本

python3.9 header缺失 – 安装下缺失的就行

如下信息最关键的是Python.h No Such file

Running setup.py install for regex … error
ERROR: Command errored out with exit status 1:
command: /data/venv-gpt-2/bin/python3 -u -c ‘import sys, setuptools, tokenize; sys.argv[0] = ‘"’"’/tmp/pip-install-yz_lezij/regex/setup.py’“'”‘; file=’“'”‘/tmp/pip-install-yz_lezij/regex/setup.py’“'”‘;f=getattr(tokenize, ‘"’“‘open’”’“‘, open)(file);code=f.read().replace(’”‘"’\r\n’“'”‘, ‘"’"’\n’“'”‘);f.close();exec(compile(code, file, ‘"’“‘exec’”’"‘))’ install --record /tmp/pip-record-inx4miu7/install-record.txt --single-version-externally-managed --compile --install-headers /data/venv-gpt-2/include/site/python3.9/regex

后来搜索stackoverflow,也可以问chatgpt,安装好缺失的部分就行

运行时参数调优

普通4核服务器上运行很慢,只能每次回答单个人问题,还要等个20秒。于是参考gpt4all官方文档,从如下方面入手调整:

  • CPU核数加大,实测16核情况下,可以在5秒内出答案,基本符合了应用需求
  • 限制回答长度,我们的需求简单,只要回答团队名称就可以,减少长度可以显著提升速度
  • 优化程序结构,预加载
  • 流式输出(提升了用户体验,但是没有缩短时间)
  • prompt工程,因为我们需求单一,就是弄清楚是哪个team来解决DoD问题,所以团队资料部分可以写死代码中加载

代码分析

项目代码

项目最核心的代码脱敏后示例如下(部分变量和文件重命名了):

from langchain.document_loaders import UnstructuredMarkdownLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.llms import GPT4All
from langchain.chains import RetrievalQA
import time
from flask import Flask, request
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

app = Flask(__name__)

markdown_path = "./test.md"
loader = UnstructuredMarkdownLoader(markdown_path)
documents = loader.load()
print("loaded documents")
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=64)
texts = text_splitter.split_documents(documents)
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
db = Chroma.from_documents(texts, embeddings, persist_directory="db")
print("embeddings")
callbacks = [StreamingStdOutCallbackHandler()]
model_path = "/data/gpt4all/ggml-gpt4all-j-v1.3-groovy.bin"
llm = GPT4All(model=model_path, n_ctx=128, backend="gptj", verbose=False, n_threads=15, callbacks=callbacks, n_predict=48)
qa = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=db.as_retriever(search_kwargs={"k": 3}),
        return_source_documents=True,
        verbose=False,
    )


def print_hi(question):
    res = qa(question)
    print("answer")
    print(time.time())
    print(res["result"])
    return res["result"]


@app.route('/', methods=['POST'])
def echo():
    data = request.get_data(as_text=True)
    print(data)
    res = print_hi(data)
    return res

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    app.run(host='0.0

库代码

代码中使用了langchain和llama,趁项目机会,分析其核心功能代码:

接口名功能开源替代
/v1/embeddings提取文本片段的特征HuggingfaceEmbedding
/v1/completions补齐文本,回答问题chatGLM

为什么要有embeddings接口?物有异名,最早marketing的搜索,是精确匹配到关键字,但是自然语言是丰富多样的,比如我要找一下气质"自然淡雅"的衣服,正好衣服广告词中也有这几个字,于是能匹配,但是用户也可能会用"小清新"去搜索,就搜索不到了。所以embeddings接口是通过"名"提取出"物"
具体算法参考:

https://time.geekbang.org/column/article/644795 有了 OpenAI 的 Embedding 接口,我们就可以把一段文本的语义表示成一段向量。而向量之间是可以计算距离的,如果向量距离少于某个阈值,就认为这两个名指的是同一个物

物有异名应对方案:

  1. 通过维护一个同义词表,好处是实现简单,坏处是维护麻烦
  2. 通过调用本地的embedding库 HuggingfaceEmbedding (比起推理,embedding其实要简单点,具备本地运行的可能)

效果展示

例子1

curl -X POST -d "according to the test.md, if I can not arrange shipment, which API may I refer to?" http://localhost:5000
 If you are unable to arrange shipment for an order, you can refer to the API `/api/v2/logistic/ship_order` to initiate logistics for the order. This API will allow you to arrange pickup, drop

例子2

if I want to arrange shipment, which API should I call?

 To arrange shipment, you should call the api/v2/logisticsship\_order/ship\_order. Use this api to initiate logistics including arrange pickup, dropoff or shipment for non-integrated logistic channels.

Here's an example of how to call the api/v2/logisticsship\_order/ship\_order API to initiate shipment logistics:

POST /api/v2/logisticsship_order/ship_order
{
“address”: “123 Main St”,
“pickup_address”: “456 Smith Ave”,
“dropoff_address”: “789 Baker Ave”,
“pickup_time”: “11:00”,
“dropoff_time”: “14:00”,
“pickup_method”: “Standard Delivery”,
“dropoff_method”: “Express Delivery”
}

Note: This is just an example and the actual implementation may vary based on the 3PL service provider and the requirements of your shipment logistics. It is always recommended to consult with your 3PL service provider or contact their support team for specific assistance.

附录:所用的公司内部API文档例子:

#api/v2/logistics/get_shipping_parameter
Use this api to get the parameter "info_needed" from the response to check if the order has pickup or dropoff or no integrate options. This api will also return the addresses and pickup time id options for the pickup method. For dropoff, it can return branch id, sender real name etc, depending on the 3PL requirements.

#/api/v2/logistics/ship_order
Use this api to initiate logistics including arrange pickup, dropoff or shipment for non-integrated logistic channels. Should call v2.logistics.get_shipping_parameter to fetch all required param first. It's recommended to initiate logistics one hour after the orders were placed since there is one-hour window buyer can cancel any order without request to seller.

#/api/v2/logistics/create_shipping_document
Use this api to create shipping document task for each order or package and this API is only available after retrieving the tracking number.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/65052.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】—— 进程等待 waitwaitpid

序言: 之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。因此,为了解决这个问题,就需要用到有关 “进程等待” 的基本知识!!&am…

【沁恒蓝牙mesh】CH58x flash分区之利用随机数作为蓝牙mesh地址

本文主要介绍了 沁恒蓝牙芯片 CH58x 的flash 分区与数据存储管理,利用随机数作为蓝牙mesh地址,蓝牙mesh采用自组网 📋 个人简介 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎&#…

python实现简单的爬虫功能

前言 Python是一种广泛应用于爬虫的高级编程语言,它提供了许多强大的库和框架,可以轻松地创建自己的爬虫程序。在本文中,我们将介绍如何使用Python实现简单的爬虫功能,并提供相关的代码实例。 如何实现简单的爬虫 1. 导入必要的…

【网络编程】利用套接字实现一个简单的网络通信(UDP实现聊天室 附上源码)

网络编程套接字 🐛预备知识🦋理解源IP地址和目的IP地址🐌认识端口号🐞 理解 "端口号" 和 "进程ID"🐜简单认识TCP协议🦟简单认识UDP协议🦗 什么是网络字节序 🕷相…

《剑指offer》(5)搜索算法、位运算、模拟

方法一&#xff1a; class Solution: def GetNumberOfK(self , nums: List[int], k: int) -> int: #从两边开始找&#xff0c;找到之后记录当前位置 left 0 right len(nums) - 1 if k not in nums: return 0 start len(nums) - 1 end 0 while left < right: if nums…

Vue2源码分析-day1

初始化数据 vue中最核心的我们都知道那就是响应式数据&#xff0c;数据的变化视图自动更新。那么我们来new一个我们自己的vue 在index.html文件下加入如下代码&#xff0c;这也是vue最常见的基本结构。data已经有了下面我们来获取data的数据 <script src"./vue.js&qu…

[openCV]基于拟合中线的智能车巡线方案V3

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…

『Samba』在Linux中实现高效访问和管理共享文件夹的基本操作与实践

&#x1f4e3;读完这篇文章里你能收获到 Samba 的安装和配置&#xff1a;详细介绍了如何在 Linux 操作系统上安装和配置 Samba 服务器共享文件夹的设置&#xff1a;指导如何选择要共享的文件夹&#xff0c;并为其设置共享名称、路径以及访问权限Samba 用户的创建&#xff1a;提…

C# App.config和Web.config加密

步骤1&#xff1a;创建加密命令 使用ASP.NET提供的命令工具aspnet_regiis来创建加密命令。 1、打开控制台窗口&#xff0c;在命令行中输入以下命令&#xff1a; cd C:\Windows\Microsoft.NET\Framework\v4.xxxxx aspnet_regiis.exe -pef connectionStrings "C:\MyAppFo…

搭建 elasticsearch8.8.2 伪集群 windows

下载windows 版本 elasticsearch8.8.2 以下链接为es 历史版本下载地址&#xff1a; Past Releases of Elastic Stack Software | Elastic windows 单节点建立方案&#xff1a; 下载安装包 elasticsearch-8.8.2-windows-x86_64.zip https://artifacts.elastic.co/download…

代码随想录算法训练营第51天|动态规划part09|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

代码随想录算法训练营第51天&#xff5c;动态规划part09&#xff5c;198.打家劫舍、213.打家劫舍II、337.打家劫舍III 198.打家劫舍 198.打家劫舍 思路&#xff1a; 仔细一想&#xff0c;当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了。 所以这里就更感觉到&a…

机器学习鱼书笔记(自用更新)

零、预知识 1.Numpy 使用 介绍&#xff1a;高效的操作多维数组的函数库。 安装&#xff1a;&#xff08;前提已经安装了python&#xff09; pip install numpy导入 import numpy as np创建数组 Numpy最重要的数据结构是多维数组&#xff08;ndarray&#xff09;。通过Numpy&…

农商行基于分类分级的数据安全管控建设实践

《数据安全法》颁布实施以来&#xff0c;以分类分级为基础&#xff0c;对数据进行差异化管理和防护&#xff0c;成为行业共识。 金融行业作为数据密集的高地&#xff0c;安全是重中之重&#xff0c;而鉴于金融数据种类和内容庞杂&#xff0c;面临规模化用数、普惠用数、跨机构共…

分布式协议与算法——Paxos算法

目录 Paxos算法Basic Paxos算法三种角色如何达成共识&#xff08;协商过程&#xff09;小结&#xff1a; Multi-Paxos算法关于 Multi-Paxos 的思考领导者优化Basic PaxosChubby 的 Multi-Paxos 实现小结 参考 Paxos算法 Paxos论文 Paxos Made Simple 、author&#xff1a;Lesli…

wireshark 安装和使用

wireshark&#xff0c;世界上最受欢迎的网络协议分析器。是一个网络流量分析器&#xff0c;或“嗅探器”&#xff0c;适用于Linux、macOS、*BSD和其他Unix和类Unix操作系统以及Windows。它使用图形用户界面库Qt以及libpcap和npcap作为数据包捕获和过滤库。 wireshark&#xff…

Flamingo

基于已有的图像模型和文本模型构建多模态模型。输入是图像、视频和文本&#xff0c;输出是文本。 Vision encoder来自预训练的NormalizerFree ResNet (NFNet)&#xff0c;之后经过图文对比损失学习。图片经过图像模型的输出是2D grid&#xff0c;视频按1FPS的频率采样后经过图…

【2种方法,jmeter用一个正则提取器提取多个值!】

jmeter中&#xff0c;用json提取器&#xff0c;一次提取多个值&#xff0c;这个很多人都会。但是&#xff0c;用正则提取器一次提取多个&#xff0c;是否可以呢&#xff1f; 肯定&#xff0c;很多人都自信满满的说&#xff0c;可以&#xff01;形如&#xff1a;token":&q…

Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

matlab使用教程(10)—脚本和函数

1.概述 MATLAB 提供了一个强大的编程语言和交互式计算环境。您可以使用此语言在 MATLAB 命令行中一次输入一个命令&#xff0c;也可以向某个文件写入一系列命令&#xff0c;按照执行任何 MATLAB 函数的相同方式来执行这些命令。使用 MATLAB 编辑器或任何其他文件编辑器可以创建…

使用HTTP隧道时如何应对目标网站的反爬虫监测?

在进行网络抓取时&#xff0c;我们常常会遇到目标网站对反爬虫的监测和封禁。为了规避这些风险&#xff0c;使用代理IP成为一种常见的方法。然而&#xff0c;如何应对目标网站的反爬虫监测&#xff0c;既能保证数据的稳定性&#xff0c;又能确保抓取过程的安全性呢&#xff1f;…