使用嵌入比较文本#

在本教程中,您将学习如何创建一个Python应用程序,该应用程序使用语义嵌入和Levenshtein相似度来比较两个输入文本。该应用程序与API服务器通信以生成嵌入,并以编程方式计算相似度指标。

嵌入是文本字符串含义的数值表示。相似的文本字符串将具有相似的数字,数字越接近,主题之间的关系越密切,即使单词不同。例如,由于“vision”和“sight”具有相似的含义,它们的嵌入可能在数值上非常接近。

Prerequisites
  • 在开始之前,请确保您的机器上已安装conda包管理器。您可以使用Anaconda Distribution或Miniconda来安装conda

  • 您必须在本地机器上下载一个sentence-similarity类型的模型。

设置您的环境#

在开始一个新的conda项目时,建议为开发创建一个新的环境。按照以下步骤为您的嵌入应用程序设置环境:

  1. 打开Anaconda提示符(在macOS/Linux上是终端)。

    提示

    如果愿意,可以从IDE(JupyterLab、PyCharm、VSCode、Spyder)中打开此终端。

  2. 创建conda环境以开发您的嵌入应用程序,并通过运行以下命令安装所需的包:

    conda create --name content-compare python numpy scikit-learn python-Levenshtein requests
    
  3. 通过运行以下命令激活您新创建的conda环境:

    conda activate content-compare
    

有关管理环境的更多信息和最佳实践,请参阅Environments

构建文本比较器#

下面,您将找到构建文本比较器所需的代码片段,并附有每一步的解释,以帮助您理解应用程序的工作原理。文本比较器结合了两种比较文本的方法:使用嵌入的语义相似性和使用Levenshtein距离的结构相似性。

语义相似性告诉我们两个文本的含义有多接近,而Levenshtein距离则通过计算将一个字符串转换为另一个字符串所需的编辑次数来查看实际字符的相似性。这些方法共同帮助我们理解两个文本字符串的相似性——它们是否看起来相似,意思是否相同,或者两者兼具。

使用您喜欢的IDE,创建一个新文件并将其命名为similarian.py

导入库#

我们正在构建的应用程序需要库来处理HTTP请求、数值操作和字符串相似度计算。

将以下代码行添加到您的 similarian.py 文件的顶部:

import requests
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
import Levenshtein

设置base_url#

为了使应用程序能够以编程方式处理文本输入以运行服务器健康检查、生成嵌入并执行其他操作,正确构建应用程序以与API服务器及其端点进行交互至关重要。

这些API端点的URL是通过将base_url与每个函数的特定/endpoint组合而成的。base_URL可以通过组合Anaconda AI Navigator中指定的服务器地址服务器端口来构建,如下所示:http://:

通过将以下行添加到您的文件中,将base_url设置为指向默认服务器地址。

base_url = 'http://localhost:8080'

提示

localhost127.0.0.1 在语义上是相同的。

添加API调用#

AI Navigator 使用 llama.cpp 的规范与 API 服务器的 /embedding 端点进行交互。

提示

API服务器也与OpenAI的/embeddings API规范兼容。

为了使您的应用程序能够与API服务器通信,您必须实现以服务器可以理解的方式调用API的函数。

GET /health#

在向服务器发送任何请求之前,最好先验证服务器是否正常运行。此函数向/health端点发送GET请求,并返回一个JSON响应,告诉你服务器的状态。

将以下行添加到您的 similarian.py 文件中:

def get_server_health():
    response = requests.get(f'{base_url}/health')
    return response.json()

POST /embedding#

要与sentence-similarity模型交互,您必须有一个访问服务器/embedding端点的函数。此函数处理输入文本并返回其向量表示(嵌入)。

将以下行添加到您的 similarian.py 文件中:

def get_embedding(input_text):
    data = {"content": input_text}
    headers = {"Content-Type": "application/json"}
    response = requests.post(f"{base_url}/embedding", json=data, headers=headers)

    if response.status_code == 200:
        return response.json()["embedding"]
    else:
        raise Exception(f"Error: {response.status_code}, {response.text}")

构建函数#

现在我们已经添加了与API服务器通信的API调用,我们需要构建应用程序的核心功能:比较两个文本字符串。这涉及到测量它们的语义(基于意义)和结构(基于字符)的相似性。

compare_texts#

此函数从main函数中获取两个文本输入,并计算语义和结构相似性分数。

将以下行添加到您的 similarian.py 文件中:

def compare_texts(text1, text2):
    # Get embeddings and calculate semantic similarity
    emb1 = get_embedding(text1)
    emb2 = get_embedding(text2)
    semantic_sim = cosine_similarity(
        np.array(emb1).reshape(1, -1),
        np.array(emb2).reshape(1, -1)
    )[0][0]

    # Calculate Levenshtein similarity
    distance = Levenshtein.distance(text1.lower(), text2.lower())
    max_length = max(len(text1), len(text2))
    levenshtein_sim = 1 - (distance / max_length)

    return semantic_sim, levenshtein_sim

main#

main 函数将其他函数联系在一起并处理用户输入。它从用户那里获取两个输入,并显示相似性计算的结果。

将以下行添加到您的 similarian.py 文件中:

def main():
    print("Enter two sentences to compare:")
    text1 = input("Sentence 1: ")
    text2 = input("Sentence 2: ")

    print("\nCalculating similarities...")

    try:
        semantic_sim, levenshtein_sim = compare_texts(text1, text2)
        print("\nResults:")
        print(f"Semantic (embedding) similarity: {semantic_sim:.2%}")
        print(f"Levenshtein (string) similarity: {levenshtein_sim:.2%}")
    except requests.exceptions.ConnectionError:
        print("\nError: Could not connect to embedding server at localhost:8080")
        print("Make sure your local embedding server is running")

if __name__ == "__main__":
    main()

与API服务器交互#

构建好你的文本比较器后,是时候比较一些文本了!

  1. 打开Anaconda AI导航器并将模型加载到API服务器

    注意

    必须是一个sentence-similarity类型的模型!

  2. 服务器地址服务器端口保留为默认值,然后点击 开始

  3. 打开终端并导航到存储similarian.py文件的目录。

    提示

    确保您仍在content-compare conda环境中。

  4. 通过运行以下命令启动文本比较器:

    python similarian.py
    

    注意

    每次运行文本比较器时,您都需要运行此命令。

  5. 输入一串文本并按Enter(Windows)/Return(Mac)。

  6. 输入一串文本,您希望将其与之前的字符串进行比较,然后再次按Enter(Windows)/Return(Mac)。

  7. 查看Anaconda AI Navigator API服务器日志。如果一切设置正确,服务器日志将填充来自应用程序的流量,从健康检查开始。

以下是与文本比较器交互的示例,假设您之前已经导航到包含similarian.py文件的目录:

(content-compare) ➜ python similarian.py
Sentence 1: That book was amazing! I did not see that twist coming!
Sentence 2: That tome was naught but wondrous! The twist therein didst elude mine keenest foresight.

Calculating similarities...

Results:
Semantic (embedding) similarity: 72.61%
Levenshtein (string) similarity: 31.82%

比较句子#

以下是一些示例,您可以使用它们来更好地理解和感受文本比较的工作原理:

Synonyms and rephrasing

尝试用两种不同的方式写相同的短语,看看即使结构相似性差异很大,语义相似性如何保持较高。

The quick brown fox jumped over the lazy dog.
The swift auburn fox leaped above the sluggish canine.
Effects of typos

尝试一些小的拼写错误,观察语义相似性如何保持一致,而由于编辑距离的增加,结构相似性下降。

The quick brown fox jumps over the lazy dog.
The quikc brn fox jumpd ovr the lazy dog.
Opposite meanings

比较结构相似但意义相反的句子。这突出了即使Levenshtein相似度保持较高,语义相似度也可能下降的情况。

I love dogs; they are the best.
I hate dogs; they are the worst.

下一步#

你可以继续开发和扩展这个文本比较器,以应对更高级的用例,例如实现一个数据库来存储嵌入,以便在大规模下进行高效比较,从而构建诸如重复内容检测器、推荐系统或文档聚类应用程序等工具。

或者,如果您已完成此项目,可以通过运行以下命令删除文件并清理您的conda环境:

conda deactivate
conda remove --name content-compare --all