本文正在参加「金石计划」
接上文OpenAI Embedding:快速实现聊天机器人(二)有讲到聊天机器人的架构和流程,这篇开始通过代码讲讲具体实现。
前言
这篇文章为了降低实现的难度,下图中提供存储和向量相似度搜索的Redis(Redis Search 模块),我先替换成CSV和余弦相似度算法。
在开发语言选择上,人工智能的应用我当然首选了Python,没有用到其它太深太复杂的技术,目的是大家能够通过这个例子快速动手实践。
数据准备
首先准备一个csv文件,以便存储文本。当然你想用txt或者其格式的文档存储都行,只要你能读出来,格式正确。
在这里,我拿MBA智库的一篇文章破窗效应(Break Pane Law; Broken windows theory)举个例子。从这篇文章我截取了各个段落的一些摘要信息,放入到一个名为knowledge_base.csv的文档中,文档只有一列,列标题为text。
代码实现
调用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变量存储情况见下图。
search_docs()函数内的这段代码执行后df变量存储情况见下图。
df["similarities"] = df.search_embeddings.apply(lambda x: cosine_similarity(x, embedding))
能看到similarities列展示了与问题相似的文本分数,因为第一行包含了破窗效应的应用实践,所以其相似度分数还蛮高的,也符合预定目标。
接下来的文章继续讲如何使用查询出来的相似文本进行提炼/优化,得到最终结果。