ChatGPT实战-Embeddings打造定制化AI智能客服

本文介绍Embeddings的基本概念,并使用最少但完整的代码讲解Embeddings是如何使用的,帮你打造专属AI聊天机器人(智能客服),你可以拿到该代码进行修改以满足实际需求。

ChatGPT的Embeddings解决了什么问题?

如果直接问ChatGPT:What is langchain? If you do not know please do not answer.,由于ChatGPT不知道2021年9月份之后的事情,而langchain比较新,是在那之后才有的,所以ChatGPT会回答不知道:

I’m sorry, but I don’t have any information on “langchain.” It appears to be a term that is not widely recognized or used in general knowledge.

如果我们用上Embeddings,用上面的问题提问,它可以给出答案:

LangChain is a framework for developing applications powered by language models.

有了这个技术,我们就可以对自己的文档进行提问,从而拓展ChatGPT的知识范围,打造定制化的AI智能客服。例如在官网接入ChatGPT,根据网站的文档让他回答用户的问题。

Embeddings相关基本概念介绍

什么是Embeddings?

在跳进代码之前,先简要介绍一下什么是Embeddings。在介绍Embeddings之前我们需要先学习一下「向量」这个概念。

我们可以将一个事物从多个维度来描述,例如声音可以从「时域」和「频域」来描述(傅里叶变换可能很多人都听过),维度拆分的越多就越能描述一个事物,在向量空间上的接近往往意味着这两个事物有更多的联系,而向量空间又是比较好计算的,于是我们可以通过计算向量来判断事物的相似程度。
向量
在自然语言处理 (NLP) 的中,Embeddings是将单词或句子转换为数值向量的一种方法。这些向量捕获单词或句子的语义,使我们能够对它们执行数学运算。例如,我们可以计算两个向量之间的余弦相似度来衡量它们在语义上的相似程度。
embedding

Embeddings使用流程讲解

如何让ChatGPT回答没有训练过的内容?流程如下,一图胜千言。
在这里插入图片描述
分步解释:

  • 首先是获取本地数据的embeddings结果,由于一次embeddings调用的token数量是有限制的,先将数据进行分段然后以依次行调用获得所有数据的embeddings结果。
  • 然后我们开始提问,同样的,将提问的内容也做一次embedding,得到一个结果。
  • 再将提问的intending结果和之前所有数据的embedded结果进行距离的计算,这里的距离就是指向量之间的距离,然后我们获取距离最近的几段段数据来作为我们提问的「上下文」(例如这里找到data2/data3是和问题最相关的内容)。
  • 获得上下文之后我们开始构造真正的问题,问题会将上下文也附属在后面一并发送给chat gpt,这样它就可以回答之前不知道的问题了。

总结来说:

之所以能够让ChatGPT回答他不知道的内容,其实是因为我们把相关的上下文传递给了他,他从上下文中获取的答案。如何确定要发送哪些上下文给他,就是通过计算向量距离得到的。

embedding实战代码(python)

让我来看看实际的代码。

前置条件

  • Python 3.6 或更高版本。
  • OpenAI API 密钥,或者其他提供API服务的也可以。
  • 安装了以下 Python 软件包: requestsbeautifulsoup4pandastiktokenopenainumpy
  • 私有文本数据集。在这个示例中,使用名为 langchainintro.txt 的文本文件,这里面是langchain官网的一些文档说明,文档比较新所以ChatGPT肯定不知道,以此来测试效果。

代码:

代码来自于OpenAI官网,我做了一些改动和精简。

import os
import numpy as np
import openai
import pandas as pd
import tiktoken
from ast import literal_eval
from openai.embeddings_utils import distances_from_embeddings
import tracebacktokenizer = tiktoken.get_encoding("cl100k_base")def get_api_key():return os.getenv('OPENAI_API_KEY')def set_openai_config():openai.api_key = get_api_key()openai.api_base = "https://openai.api2d.net/v1"def remove_newlines(serie):serie = serie.str.replace('\n', ' ')serie = serie.str.replace('\\n', ' ')serie = serie.str.replace('  ', ' ')serie = serie.str.replace('  ', ' ')return seriedef load_text_files(file_name):with open(file_name, "r", encoding="UTF-8") as f:text = f.read()return textdef prepare_directory(dir_name="processed"):if not os.path.exists(dir_name):os.mkdir(dir_name)def split_into_many(text, max_tokens):# Split the text into sentencessentences = text.split('. ')# Get the number of tokens for each sentencen_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]chunks = []tokens_so_far = 0chunk = []# Loop through the sentences and tokens joined together in a tuplefor sentence, token in zip(sentences, n_tokens):# If the number of tokens so far plus the number of tokens in the current sentence is greater# than the max number of tokens, then add the chunk to the list of chunks and reset# the chunk and tokens so farif tokens_so_far + token > max_tokens:chunks.append(". ".join(chunk) + ".")chunk = []tokens_so_far = 0# If the number of tokens in the current sentence is greater than the max number of# tokens, split the sentence into smaller parts and add them to the chunkwhile token > max_tokens:part = sentence[:max_tokens]chunk.append(part)sentence = sentence[max_tokens:]token = len(tokenizer.encode(" " + sentence))# Otherwise, add the sentence to the chunk and add the number of tokens to the totalchunk.append(sentence)tokens_so_far += token + 1# Add the last chunk to the list of chunksif chunk:chunks.append(". ".join(chunk) + ".")return chunksdef shorten_texts(df, max_tokens):shortened = []# Loop through the dataframefor row in df.iterrows():# If the text is None, go to the next rowif row[1]['text'] is None:continue# If the number of tokens is greater than the max number of tokens, split the text into chunksif row[1]['n_tokens'] > max_tokens:shortened += split_into_many(row[1]['text'], max_tokens)# Otherwise, add the text to the list of shortened textselse:shortened.append(row[1]['text'])df = pd.DataFrame(shortened, columns=['text'])df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))return dfdef create_embeddings(df):df['embeddings'] = df.text.apply(lambda x: openai.Embedding.create(input=x, engine='text-embedding-ada-002')['data'][0]['embedding'])df.to_csv('processed/embeddings.csv')return dfdef load_embeddings():df = pd.read_csv('processed/embeddings.csv', index_col=0)df['embeddings'] = df['embeddings'].apply(literal_eval).apply(np.array)return dfdef create_context(question, df, max_len=1800, size="ada"
):"""Create a context for a question by finding the most similar context from the dataframe"""# print(f'start create_context')# Get the embeddings for the questionq_embeddings = openai.Embedding.create(input=question, engine='text-embedding-ada-002')['data'][0]['embedding']# print(f'q_embeddings:{q_embeddings}')# Get the distances from the embeddingsdf['distances'] = distances_from_embeddings(q_embeddings, df['embeddings'].values, distance_metric='cosine')# print(f'df[distances]:{df["distances"]}')returns = []cur_len = 0# Sort by distance and add the text to the context until the context is too longfor i, row in df.sort_values('distances', ascending=True).iterrows():# print(f'i:{i}, row:{row}')# Add the length of the text to the current lengthcur_len += row['n_tokens'] + 4# If the context is too long, breakif cur_len > max_len:break# Else add it to the text that is being returnedreturns.append(row["text"])# Return the contextreturn "\n\n###\n\n".join(returns)def answer_question(df,model="text-davinci-003",question="Am I allowed to publish model outputs to Twitter, without a human review?",max_len=1800,size="ada",debug=False,max_tokens=150,stop_sequence=None
):"""Answer a question based on the most similar context from the dataframe texts"""context = create_context(question,df,max_len=max_len,size=size,)# If debug, print the raw model responseif debug:print("Context:\n" + context)print("\n\n")prompt = f"Answer the question based on the context below, \n\nContext: {context}\n\n---\n\nQuestion: {question}\nAnswer:"messages = [{'role': 'user','content': prompt}]try:# Create a completions using the questin and contextresponse = openai.ChatCompletion.create(messages=messages,temperature=0,max_tokens=max_tokens,stop=stop_sequence,model=model,)return response["choices"][0]["message"]["content"]except Exception as e:# print stacktraceback.print_exc()print(e)return ""def main():# 设置API keyset_openai_config()# 载入本地数据texts = []text = load_text_files("langchainintro.txt")texts.append(('langchainintro', text))prepare_directory("processed")# 创建一个dataframe,包含fname和text两列df = pd.DataFrame(texts, columns=['fname', 'text'])df['text'] = df.fname + ". " + remove_newlines(df.text)df.to_csv('processed/scraped.csv')# 计算token数量df.columns = ['title', 'text']df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))# print(f'{df}')df = shorten_texts(df, 500)# 如果processed/embeddings.csv已经存在,直接load,不存在则createif os.path.exists('processed/embeddings.csv'):df = load_embeddings()else:df = create_embeddings(df)print(f"What is langchain? If you do not know please do not answer.")ans = answer_question(df, model='gpt-3.5-turbo', question="What is langchain? If you do not know please do not answer.", debug=False)print(f'ans:{ans}')if __name__ == '__main__':main()

代码流程与时序图的流程基本一致,注意api_key需要放入环境变量,也可以自己改动。

如果直接问ChatGPT:What is langchain? If you do not know please do not answer.,ChatGPT会回答不知道:

I’m sorry, but I don’t have any information on “langchain.” It appears to be a term that is not widely recognized or used in general knowledge.

运行上面的代码,它可以给出答案:

LangChain is a framework for developing applications powered by language models.

可以看到它使用了我们提供的文档来回答。

拓展

  • 注意token消耗,如果你的本地数据非常多,embedding阶段将会消耗非常多的token,请注意使用。
  • embedding阶段仍然会将本地数据传给ChatGPT,如果你有隐私需求,需要注意。
  • 一般生产环境会将向量结果存入「向量数据库」而不是本地文件,此处为了演示直接使用的文本文件存放。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上海亚商投顾:三大指数小幅下跌 光刻机概念股午后走强

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 三大指数昨日小幅调整,创业板指走势较弱。减肥药概念股继续大涨,常山药业2连板&#x…

linux( CentOs)对mysql基本操作和密码修改

1.mysql登录 mysql -uroot -p 2.显示所有数据库 Show databases; 3.生产过程中改密码 use mysql ; 查看user表中的user、host、password信息。 select user,host,password from user; select host,user from user;使用“GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIE…

Linux调试器-gdb使用

文章目录 前言一、pandas是什么?1、gdb介绍2、gdb使用2.1 启动gdb和退出gdb2.2 list显示代码命令2. run运行程序命令2.3 break设置断点命令2.4 delete删除断点命令2.5 next逐过程执行命令2.6 step逐语句向下执行命令2.7 print打印表达式值命令2.8 bt命令和finish命令…

初识C语言——详细入门一(系统性学习day4)

目录 前言 一、C语言简单介绍、特点、基本构成 简单介绍: 特点: 基本构成: 二、认识C语言程序 标准格式: 简单C程序: 三、基本构成分类详细介绍 (1)关键字 (2&#xf…

插拔结构脉冲离子风工作原理

脉冲离子风机有着特殊的结构-插拔结构,清洁保养维修更简单、更安全;核心部件模块化;它有着超强的消除静电能。 脉冲台式离子风机的安装方法:将离子风机置于台面上或悬挂于台面上,插上电源插头,打开风机,调节…

微信群发一次能发1000个好友了!你发现了吗?

微信作为我们日常交流的主要工具之一 群发功能在我们的日常生活中也非常实用 但有时候 比如在新年期间 需要向所有客户发送祝福时 在公司做活动期间 向所有客户发起邀约时 如果一个一个点击来发送信息 会非常麻烦 但是!! 我今天发现微信 已经…

部署ik分词器

部署ik分词器 案例版本:elasticsearch-analysis-ik-8.6.2 ​ ES默认自带的分词器对中文处理不够友好,创建倒排索引时可能达不到我们想要的结果,然而IK分词器能够很好的支持中文分词 ​ 因为是集群部署,所以每台服务器中的ES都需…

HarmonyOS应用开发—资源分类与访问

应用开发过程中,经常需要用到颜色、字体、间距、图片等资源,在不同的设备或配置中,这些资源的值可能不同。 应用资源:借助资源文件能力,开发者在应用中自定义资源,自行管理这些资源在不同的设备或配置中的表…

C语言指针,深度长文全面讲解

指针对于C来说太重要。然而,想要全面理解指针,除了要对C语言有熟练的掌握外,还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能的通过一篇文章完全讲解指针。 为什么需要指针? 指针解决了一些编程中基本的问题。…

9.19作业

TCP服务器 //创建流式套接字int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd < 0){ERR_MSG("socket"); return -1;}printf("socket create success sfd%d\n", sfd);//允许端口快速复用in…

MQTT Paho Android 支持SSL/TLS(亲测有效)

MQTT Paho Android 支持SSL/TLS(亲测有效) 登录时支持ssl的交互 这是调测登录界面设计 代码中对ssl/tls的支持 使用MqttAndroidClient配置mqtt客户端请求时&#xff0c;不加密及加密方式连接存在以下几点差异&#xff1a; url及端口差异 val uri: String if (tlsConnect…

[npm]脚手架本地全局安装1

[npm]脚手架本地全局安装1 npm link 全局安装npm install 全局安装卸载全局安装的脚手架 该文章是你的脚手架已经开发完成的前提下&#xff0c;你想要本地全局安装该脚手架&#xff0c;便于本地使用脚手架的命令的情况 npm link 全局安装 如果本地开发的项目是个脚手架&#…

《数据结构、算法与应用C++语言描述》使用C++语言实现二维数组下三角矩阵

《数据结构、算法与应用C语言描述》使用C语言实现二维数组下三角矩阵 下三角矩阵定义 如下图所示&#xff1a; 代码实现 _11lowerTriangularMatrix.h 模板类 /* Project name : allAlgorithmsTest Last modified Date: 2022年8月13日17点38分 Last Version: V1.0 D…

oracle创建表空间、用户、权限以及导入dmp文件

创建表空间 create tablespace A_DATA logging datafile F:\CODEAPP\ORACLE\ORADATA\A_DATA01.DBF size 50m autoextend on next 50m maxsize 32767m extent management local; -- 这个语句将创建一个大小为50MB的数据文件&#xff0c;启用自动扩展功能&#xff0c;每次扩展50…

Java21 LTS版本

一、前言 除了众所周知的 JEP 之外&#xff0c;Java 21 还有更多内容。首先请确认 java 版本&#xff1a; $ java -version openjdk version "21" 2023-09-19 OpenJDK Runtime Environment (build 2135-2513) OpenJDK 64-Bit Server VM (build 2135-2513, mixed mo…

zemax像质评价

1、外形图 1.1二维外形图 如图所示&#xff0c;展示镜头的侧面图 可以通过设置改变图中显示的内容&#xff1a; 起始面&#xff1a;绘图的第一个面 终止面&#xff1a;绘图的最后一个面 光线数&#xff1a;画出的光线数&#xff08;上图中的一个颜色就是7根线&#xff09; …

使用Visual Leak Detector排查内存泄漏问题

目录 1、VLD工具概述 2、下载并安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明 3.1、安装目录及文件说明 3.2、关于32位和64位版本的详细说明 4、在工程中引入VLD 5、内存泄漏检测实例讲解 5.1、程序启动报错 5.2、启动调试&#xff0c;查看内存泄漏报…

【深度学习-第3篇】使用MATLAB快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例

在本文中&#xff0c;我们将介绍如何使用 MATLAB 中的 Convolutional Neural Network&#xff08;CNN&#xff09;进行分类任务。我们将使用 MATLAB 的 Deep Learning Toolbox 来创建、训练和评估 CNN。 一、一个简单的案例 1 安装和准备 首先&#xff0c;确保已安装 MATLAB…

Prometheus+Grafana可视化监控【Redis状态】

文章目录 一、安装Docker二、安装Redis数据库(Docker容器方式)三、安装Prometheus四、安装Grafana五、Pronetheus和Grafana相关联六、安装redis_exporter七、Grafana添加Redis监控模板 一、安装Docker 注意&#xff1a;我这里使用之前写好脚本进行安装Docker&#xff0c;如果已…

华为云云耀云服务器L实例评测|认识redis未授权访问漏洞 漏洞的部分复现 设置连接密码 redis其他命令学习

前言 最近华为云云耀云服务器L实例上新&#xff0c;也搞了一台来玩&#xff0c;期间遇到过MySQL数据库被攻击的情况&#xff0c;数据丢失&#xff0c;还好我有几份备份&#xff0c;没有造成太大的损失。昨天收到华为云的邮箱提醒&#xff0c;我的redis数据库没有设置密码&…