高级教程:在 MLflow 中使用 OpenAI 的嵌入支持

欢迎阅读本关于在 MLflow 框架中实现 OpenAI 嵌入的高级指南。本教程深入探讨了 OpenAI 强大嵌入的配置和使用,这是现代机器学习模型的关键组件。

Download this Notebook

理解嵌入

嵌入是一种表示学习的形式,其中单词、短语,甚至整个文档被转换为高维空间中的向量。这些向量捕捉语义意义,使模型能够更有效地理解和处理语言。嵌入在自然语言处理(NLP)中被广泛用于文本分类、情感分析和语言翻译等任务。

嵌入的工作原理

嵌入通过将文本数据映射到向量来工作,使得向量之间的距离和方向代表单词或短语之间的关系。例如,在一个训练良好的嵌入空间中,同义词位于更近的位置,而无关的术语则相距较远。这种空间排列使得算法能够识别上下文和语义,增强其解释和响应自然语言的能力。

在本教程中

  • 嵌入端点配置: 在 MLflow 中设置和使用 OpenAI 的嵌入端点。

  • 实际应用:实际示例,比较多个网页的文本内容,以确定它们在特定上下文内容中的相似程度。

  • 效率和精度提升:使用 OpenAI 嵌入提升模型性能的技术。

在本教程结束时,您将全面了解如何在您的 MLflow 项目中集成和利用 OpenAI 嵌入,利用先进的 NLP 技术。您还将看到一个使用文档文本嵌入来比较其相似性的实际应用。这个用例在网页内容开发中特别有用,因为在执行搜索引擎优化 (SEO) 时,确保网站页面内容彼此不过于相似(这可能导致页面排名下降)是一项关键任务。

必需的包

为了运行本教程,您需要从 PyPI 安装 beautifulsoup4

让我们深入嵌入的世界,探索它们对机器学习模型的变革性影响!

[1]:
import warnings

# Disable a few less-than-useful UserWarnings from setuptools and pydantic
warnings.filterwarnings("ignore", category=UserWarning)
[2]:
import os

import numpy as np
import openai
import requests
from bs4 import BeautifulSoup
from sklearn.metrics.pairwise import cosine_similarity, euclidean_distances

import mlflow
from mlflow.models.signature import ModelSignature
from mlflow.types.schema import ColSpec, ParamSchema, ParamSpec, Schema, TensorSpec

assert "OPENAI_API_KEY" in os.environ, " OPENAI_API_KEY environment variable must be set"

将 OpenAI 模型与 MLflow 集成以进行文档相似度分析

在本教程部分,我们演示了在MLflow中设置和使用OpenAI嵌入模型进行文档相似性任务的过程。

关键步骤

  1. 设置 MLflow 实验:我们首先在 MLflow 中设置实验上下文,特别是针对文档相似性,使用 mlflow.set_experiment("Documentation Similarity")

  2. 在MLflow中记录模型: 我们启动一个MLflow运行,并记录元数据和访问配置参数以与特定的OpenAI端点通信。我们在这里选择的OpenAI端点指向模型“text-embedding-ada-002”,选择它是因为其强大的嵌入能力。在此步骤中,我们详细说明这些访问配置、嵌入任务、输入/输出模式以及批量大小等参数。

  3. 加载用于使用的记录模型:在记录 MLflow 模型后,我们使用 MLflow 的 pyfunc 模块加载它。这是在 MLflow 生态系统中应用模型执行文档相似性任务的关键步骤。

这些步骤对于将访问 OpenAI 的嵌入模型集成到 MLflow 中至关重要,有助于进行文档相似性分析等高级 NLP 操作。

[3]:
mlflow.set_experiment("Documenatation Similarity")

with mlflow.start_run():
    model_info = mlflow.openai.log_model(
        model="text-embedding-ada-002",
        task=openai.embeddings,
        artifact_path="model",
        signature=ModelSignature(
            inputs=Schema([ColSpec(type="string", name=None)]),
            outputs=Schema([TensorSpec(type=np.dtype("float64"), shape=(-1,))]),
            params=ParamSchema([ParamSpec(name="batch_size", dtype="long", default=1024)]),
        ),
    )

# Load the model in pyfunc format
model = mlflow.pyfunc.load_model(model_info.model_uri)

网页文本提取用于嵌入分析

本教程的这一部分介绍了用于从网页中提取和准备文本的函数,这是在应用嵌入模型进行分析之前的至关重要的一步。

功能概览

  1. insert_space_after_tags:

    • 在BeautifulSoup对象中特定HTML标签后添加空格,以提高文本可读性。

  2. extract_text_from_url:

    • 从指定网页部分的URL和目标ID中提取文本。从标签中过滤和组织文本,如,

    • ,和

      , 排除某些不相关的部分。

这些功能对于预处理网页内容至关重要,确保输入到嵌入模型中的文本是干净的、相关的和结构良好的。

[4]:
def insert_space_after_tags(soup, tags):
    """
    Insert a space after each tag specified in the provided BeautifulSoup object.

    :param soup: BeautifulSoup object representing the parsed HTML.
    :param tags: List of tag names (as strings) after which space should be inserted.
    """
    for tag_name in tags:
        for tag in soup.find_all(tag_name):
            tag.insert_after(" ")


def extract_text_from_url(url, id):
    """
    Extract and return text content from a specific section of a webpage.
    """
    try:
        response = requests.get(url)
        response.raise_for_status()  # Raises HTTPError for bad requests (4XX, 5XX)
    except requests.exceptions.RequestException as e:
        return f"Request failed: {e}"

    soup = BeautifulSoup(response.text, "html.parser")
    target_div = soup.find("div", {"class": "section", "id": id})
    if not target_div:
        return "Target element not found."

    insert_space_after_tags(target_div, ["strong", "a"])

    content_tags = target_div.find_all(["h1", "h2", "h3", "h4", "h5", "h6", "li", "p"])
    filtered_tags = [
        tag
        for tag in content_tags
        if not (
            (tag.name == "li" and tag.find("p") and tag.find("a", class_="reference external"))
            or (tag.name == "p" and tag.find_parent("ul"))
            or (tag.get_text(strip=True).lower() == "note")
        )
    ]

    return "\n".join(tag.get_text(separator=" ", strip=True) for tag in filtered_tags)

详细工作流程:

  • 函数 extract_text_from_url 首先使用 requests 库获取网页内容。

  • 然后使用 BeautifulSoup 解析 HTML 内容。

  • 特定的HTML标签被用于文本提取,确保内容与嵌入分析相关且结构良好。

  • insert_space_after_tags 函数在 extract_text_from_url 中被调用,以提高提取后文本的可读性。

测量嵌入之间的相似性和距离

在本教程的下一部分中,我们利用 sklearn 中的两个函数来测量文档嵌入之间的相似性和距离,这对于评估和比较基于文本的机器学习模型至关重要。

功能概述

  1. 余弦相似度:

    • 目的: 计算两个嵌入向量之间的余弦相似度。

    • 工作原理:此函数通过计算两个向量之间夹角的余弦来计算相似度,这是一种常用的评估两份文档在内容上相似程度的方法。

    • 相关性:在自然语言处理(NLP)中非常有用,特别是在文档检索和聚类等任务中,目标是为了找到内容相似的文档。

  2. euclidean_distances:

    • 目的:计算两个嵌入向量之间的欧几里得距离。

    • 功能: 类似于 cosine_similarity,该函数计算欧几里得距离,这是嵌入空间中两点之间的“直线”距离。这一度量对于理解两个文档之间的差异非常有用。

    • 在NLP中的相关性: 提供了一种更直观的物理距离度量,对于文档分类和异常检测等任务非常有用。

这些功能对于分析和比较嵌入模型的输出至关重要,提供了关于不同文本数据之间相似性和差异性关系的见解。

使用嵌入向量比较网页

本教程的这一部分介绍了一个函数 compare_pages,该函数旨在使用嵌入模型比较两个网页的内容。该函数对于理解两个给定网页在文本内容方面的相似性或差异性至关重要。

功能概述

  • 函数名称: compare_pages

  • 目的: 比较两个网页并根据其内容返回相似度评分。

  • 参数:

    • url1url2: 要比较的网页的URL。

    • id1id2: 每个页面主文本内容 div 的目标 ID。

工作原理

  1. 文本提取:该功能首先使用 extract_text_from_url 函数从每个网页的指定部分提取文本。

  2. 嵌入预测:然后,它使用之前加载的 OpenAI 模型为提取的文本生成嵌入。

  3. 相似性与距离测量: 该函数计算两个嵌入之间的余弦相似度和欧几里得距离。这些指标提供了一个量化的度量,用于衡量网页内容之间的相似性或差异性。

  4. 结果: 返回一个包含余弦相似度分数和欧几里得距离的元组。如果文本提取失败,则返回错误消息。

实际应用

此功能在需要比较不同网页内容的场景中特别有用,例如在内容策划、抄袭检测或用于SEO目的的相似性分析中。

通过利用嵌入和相似度度量的力量,compare_pages 提供了一种强大的方法,用于定量评估网页内容之间的相似性和差异。

[5]:
def compare_pages(url1, url2, id1, id2):
    """
    Compare two webpages and return the similarity score.

    :param url1: URL of the first webpage.
    :param url2: URL of the second webpage.
    :param id1: The target id for the div containing the main text content of the first page
    :param id2: The target id for the div containing the main text content of the second page
    :return: A tuple of floats representing the similarity score for cosine similarity and euclidean distance.
    """
    text1 = extract_text_from_url(url1, id1)
    text2 = extract_text_from_url(url2, id2)

    if text1 and text2:
        embedding1 = model.predict([text1])
        embedding2 = model.predict([text2])

        return (
            cosine_similarity(embedding1, embedding2),
            euclidean_distances(embedding1, embedding2),
        )
    else:
        return "Failed to retrieve content."

MLflow 文档页面之间的相似性分析

在本教程部分,我们通过比较MLflow文档中的两个特定页面来演示 compare_pages 函数的实际应用。我们的目标是评估MLflow 2.8.1版本中主大型语言模型(LLMs)页面与LLM评估页面内容的相似程度。

流程概述

  • 目标网页

  • 内容ID:我们使用 ‘llms’ 作为主LLMs页面的ID,使用 ‘mlflow-llm-evaluate’ 作为LLM评估页面的ID,以定位特定的内容部分。

  • 比较执行:调用 compare_pages 函数,并传入这些URL和内容ID以执行分析。

结果

  • 余弦相似度和欧几里得距离: 该函数返回两个关键指标:

    • 余弦相似度:测量两页嵌入向量之间夹角的余弦值。值越高表示相似度越大。

    • 欧几里得距离:表示嵌入空间中两点之间的‘直线’距离,数值越低表示相似度越高。

解释

结果显示了高度的余弦相似性(0.8792),这表明两页内容在上下文和涵盖的主题方面非常相似。欧几里得距离为0.4914,虽然相对较低,但提供了补充视角,表明内容具有一定程度的独特性。

结论

这项分析突出了使用嵌入和相似性度量来比较网页内容的有效性。在实际应用中,它有助于理解文档的重叠和差异,有助于内容优化、减少冗余,并确保对主题的全面覆盖。

[6]:
# Get the similarity between the main LLMs page in the MLflow Docs and the LLM Evaluation page for the 2.8.1 release of MLflow

llm_cosine, llm_euclid = compare_pages(
    url1="https://www.mlflow.org/docs/2.8.1/llms/index.html",
    url2="https://www.mlflow.org/docs/2.8.1/llms/llm-evaluate/index.html",
    id1="llms",
    id2="mlflow-llm-evaluate",
)

print(
    f"The cosine similarity between the LLMs page and the LLM Evaluation page is: {llm_cosine} and the euclidean distance is: {llm_euclid}"
)
The cosine similarity between the LLMs page and the LLM Evaluation page is: [[0.879243]] and the euclidean distance is: [[0.49144073]]

MLflow LLMs 和插件页面相似性的简要概述

本节展示了对MLflow大型语言模型(LLMs)页面与2.8.1版本中插件页面的快速相似性分析。

分析执行

结果

  • 余弦相似度: 0.6806,表明内容具有中等相似度。

  • 欧几里得距离: 0.7992,表明两页内容和主题有明显差异。

结果反映出LLMs和Plugins页面之间存在中等程度的相似性,其内容具有显著的独特性。此分析有助于理解MLflow文档中不同部分之间的关系和内容重叠。

[7]:
# Get the similarity between the main LLMs page in the MLflow Docs and the Plugins page for the 2.8.1 release of MLflow

plugins_cosine, plugins_euclid = compare_pages(
    url1="https://www.mlflow.org/docs/2.8.1/llms/index.html",
    url2="https://www.mlflow.org/docs/2.8.1/plugins.html",
    id1="llms",
    id2="mflow-plugins",
)

print(
    f"The cosine similarity between the LLMs page and the MLflow Projects page is: {plugins_cosine} and the euclidean distance is: {plugins_euclid}"
)
The cosine similarity between the LLMs page and the MLflow Projects page is: [[0.68062298]] and the euclidean distance is: [[0.79922088]]

教程回顾:在 MLflow 中利用 OpenAI 嵌入

在本教程结束之际,让我们回顾一下我们在MLflow框架中使用OpenAI嵌入时探讨的关键概念和技术。

关键要点

  1. 在 MLflow 中集成 OpenAI 模型:

    • 我们学习了如何在 MLflow 中记录和加载 OpenAI 的 “text-embedding-ada-002” 模型,这是在机器学习工作流中利用这些嵌入的关键步骤。

  2. 文本提取与预处理

    • 本教程介绍了从网页中提取和预处理文本的方法,确保数据干净且结构化,以便进行嵌入分析。

  3. 计算相似度和距离

    • 我们深入研究了用于测量文档嵌入之间余弦相似度和欧几里得距离的函数,这对于比较文本内容至关重要。

  4. 实际应用:网页内容比较

    • 通过比较不同的 MLflow 文档页面,展示了这些概念的实际应用。我们使用 OpenAI 模型生成的嵌入分析了它们内容的相似性和差异。

  5. 解释结果

    • 本教程提供了对相似性和距离度量结果的解读见解,强调了它们在理解内容关系中的相关性。

结论

本高级教程旨在提升你在MLflow中应用OpenAI嵌入的技能,重点在于实际应用,如文档相似性分析。通过整合这些强大的NLP工具,我们展示了如何从文本数据中提取更多价值和洞察,这是现代机器学习项目中的关键方面。

我们希望本指南对您在MLflow框架中理解和应用OpenAI嵌入有所帮助和指导。

下一步是什么?

要继续您的学习之旅,请参阅 MLflow 的 OpenAI 风格的进阶教程