OpenAI Embedding:快速实现聊天机器人(三)

1,468 阅读2分钟

本文正在参加「金石计划」

接上文OpenAI Embedding:快速实现聊天机器人(二)有讲到聊天机器人的架构和流程,这篇开始通过代码讲讲具体实现。

前言

这篇文章为了降低实现的难度,下图中提供存储和向量相似度搜索的Redis(Redis Search 模块),我先替换成CSV和余弦相似度算法。

image.png

在开发语言选择上,人工智能的应用我当然首选了Python,没有用到其它太深太复杂的技术,目的是大家能够通过这个例子快速动手实践。

数据准备

首先准备一个csv文件,以便存储文本。当然你想用txt或者其格式的文档存储都行,只要你能读出来,格式正确。

在这里,我拿MBA智库的一篇文章破窗效应(Break Pane Law; Broken windows theory)举个例子。从这篇文章我截取了各个段落的一些摘要信息,放入到一个名为knowledge_base.csv的文档中,文档只有一列,列标题为text。

image.png

代码实现

调用Azure OpenAI服务使用嵌入模型获取文本的embedding向量

def get_native_embeddings(text):  
    url = f"{ENDPOINT}/openai/deployments/{MODEL_NAME}/embeddings?api-version=2022-12-01"  
    headers = {"api-key": SUBSCRIPTION_KEY}  
    data = {  
    'input': text,  
    'user': uuid.uuid4().urn  
    }  
    response = requests.post(url, headers=headers, json=data)  
    response_json = response.json()  
    # 数据解析,获取embedding  
    return np.array(response_json['data'][0]['embedding'], dtype=np.float32)

读取知识库(即文档)到DataFrame,将每段文本转成embedding向量并存回DataFrame

def get_embeddings():  
    df = pd.read_csv("../knowledge_base.csv", encoding='gbk')  
    df["text"] = df["text"].apply(lambda x: x.replace("\n", " ")).tolist()  
    df['search_embeddings'] = df["text"].apply(lambda x: get_native_embeddings(x)).tolist()  
    return df

拿问题去搜索文档中相似的文本,并提取相似TopN。这里要记得引用库from openai.embeddings_utils import cosine_similarity去使用余弦相似度算法。

def search_docs(df, user_query, top_n=3, to_print=True):  
    embedding = get_native_embeddings(user_query)  
    df["similarities"] = df.search_embeddings.apply(lambda x: cosine_similarity(x, embedding))  
    res = (  
    df.sort_values("similarities", ascending=False)  
    .head(top_n)  
    )  
    # if to_print:  
    # print(res)  
    return res

启动,调用get_embeddings获取文本的embedding向量,并执行问题的搜索

dataframe = get_embeddings();  
res = search_docs(dataframe, "破镜效应的应用实践", top_n=4)
print(res)

运行结果

get_embeddings()函数执行过后的dataframe变量存储情况见下图。

image.png

search_docs()函数内的这段代码执行后df变量存储情况见下图。

df["similarities"] = df.search_embeddings.apply(lambda x: cosine_similarity(x, embedding))

image.png

能看到similarities列展示了与问题相似的文本分数,因为第一行包含了破窗效应的应用实践,所以其相似度分数还蛮高的,也符合预定目标。


接下来的文章继续讲如何使用查询出来的相似文本进行提炼/优化,得到最终结果。