David Hope

使用 OpenTelemetry 和 Elastic 监控 OpenAI API 和 GPT 模型

准备好被这种用于监控尖端 ChatGPT 应用程序的颠覆性方法所震撼吧!随着 ChatGPT 现象席卷全球,现在是时候使用 OpenTelemetry 和 Elastic Observability 来增强您的监控能力了。

阅读时长 11 分钟
Monitor OpenAI API and GPT models with OpenTelemetry and Elastic

ChatGPT 现在非常火爆,它已经让互联网崩溃了。作为 ChatGPT 的忠实用户和 ChatGPT 应用程序的开发者,我对这项技术的可能性感到非常兴奋。我看到的情况是,基于 ChatGPT 的解决方案将呈指数级增长,人们将需要监控这些解决方案。

由于这是一项相当新的技术,我们不希望用专有技术来给我们的闪亮新代码增加负担,对吧?当然不希望,这就是为什么我们将在本博客中使用 OpenTelemetry 来监控我们的 ChatGPT 代码。这对我来说尤其重要,因为我最近创建了一个从 Zoom 通话生成会议记录的服务。如果我要将此服务发布到公共领域,它会花费我多少钱,以及我如何确保它可用?

OpenAI API 来解救

毫无疑问,OpenAI API 非常棒。它还在每个 API 调用的每个响应中为我们提供了如下信息,这可以帮助我们了解自己的收费情况。通过使用令牌计数、模型以及 OpenAI 在其网站上公布的价格,我们可以计算出成本。问题是,我们如何将这些信息获取到我们的监控工具中?

{
  "choices": [
    {
      "finish_reason": "length",
      "index": 0,
      "logprobs": null,
      "text": "\n\nElastic is an amazing observability tool because it provides a comprehensive set of features for monitoring"
    }
  ],
  "created": 1680281710,
  "id": "cmpl-70CJq07gibupTcSM8xOWekOTV5FRF",
  "model": "text-davinci-003",
  "object": "text_completion",
  "usage": {
    "completion_tokens": 20,
    "prompt_tokens": 9,
    "total_tokens": 29
  }
}

OpenTelemetry 来解救

OpenTelemetry 真的是一个非常出色的作品。多年来,它得到了如此多的采用和投入,似乎真的已经到了我们可以称之为可观测性的 Linux 的地步。我们可以使用它来记录日志、指标和跟踪,并以厂商中立的方式将其导入我们最喜欢的可观测性工具 — 在本例中为 Elastic Observability。

借助 Python 中最新最好的 otel 库,我们可以自动检测外部调用,这将帮助我们了解 OpenAI 调用的性能。让我们先来看看我们的示例 Python 应用程序,它实现了 Flask 和 ChatGPT API,并且还具有 OpenTelemetry。如果您想自己尝试一下,请查看本博客末尾的 GitHub 链接并按照以下步骤操作。

设置 Elastic Cloud 帐户(如果您还没有帐户)

  1. https://elastic.ac.cn/cloud/elasticsearch-service/signup 注册为期两周的免费试用。
  2. 创建部署。

登录后,单击添加集成

单击 APM 集成

然后向下滚动以获取本博客所需的详细信息

请务必设置以下环境变量,将变量替换为您从上面 Elastic 获取的数据,以及从 此处 获取的 OpenAI 数据,然后在命令行上运行这些导出命令。

export OPEN_AI_KEY=sk-abcdefgh5ijk2l173mnop3qrstuvwxyzab2cde47fP2g9jij
export OTEL_EXPORTER_OTLP_AUTH_HEADER=abc9ldeofghij3klmn
export OTEL_EXPORTER_OTLP_ENDPOINT=https://123456abcdef.apm.us-west2.gcp.elastic-cloud.com:443

并安装以下 Python 库

pip3 install opentelemetry-api
pip3 install opentelemetry-sdk
pip3 install opentelemetry-exporter-otlp
pip3 install opentelemetry-instrumentation
pip3 install opentelemetry-instrumentation-requests
pip3 install openai
pip3 install flask

以下是我们用于示例应用程序的代码。在现实世界中,这应该是您自己的代码。它所做的就是使用以下消息调用 OpenAI API:“为什么 Elastic 是一款出色的可观测性工具?”

import openai
from flask import Flask
import monitor  # Import the module
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
import urllib
import os
from opentelemetry import trace
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.requests import RequestsInstrumentor

# OpenTelemetry setup up code here, feel free to replace the “your-service-name” attribute here.
resource = Resource(attributes={
    SERVICE_NAME: "your-service-name"
})
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint=os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT'),
        headers="Authorization=Bearer%20"+os.getenv('OTEL_EXPORTER_OTLP_AUTH_HEADER')))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
RequestsInstrumentor().instrument()



# Initialize Flask app and instrument it

app = Flask(__name__)
# Set OpenAI API key
openai.api_key = os.getenv('OPEN_AI_KEY')


@app.route("/completion")
@tracer.start_as_current_span("do_work")
def completion():
    response = openai.Completion.create(
        model="text-davinci-003",
        prompt="Why is Elastic an amazing observability tool?",
        max_tokens=20,
        temperature=0
    )
    return response.choices[0].text.strip()

if __name__ == "__main__":
    app.run()

任何在这里使用 Python 实现 OpenTelemetry 的人都应该非常熟悉此代码 — 没有什么特别的魔法。魔法发生在您可以自由使用来检测自己的 OpenAI 应用程序的“monitor”代码中。

捣鼓

在 monitor.py 代码中,您会看到我们做了一些称为“Monkey Patching”的事情。Monkey patching 是 Python 中的一种技术,通过修改其属性或方法来动态修改类或模块在运行时的行为。Monkey patching 允许您更改类或模块的功能,而无需修改其源代码。当您需要修改现有类或模块的行为,而您无法控制或无法直接修改时,它会很有用。

我们在这里要做的是修改“Completion”调用的行为,以便我们可以窃取响应指标并将它们添加到我们的 OpenTelemetry span 中。您可以在下面看到我们是如何做的

def count_completion_requests_and_tokens(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        counters['completion_count'] += 1
        response = func(*args, **kwargs)
        token_count = response.usage.total_tokens
        prompt_tokens = response.usage.prompt_tokens
        completion_tokens = response.usage.completion_tokens
        cost = calculate_cost(response)
        strResponse = json.dumps(response)
        # Set OpenTelemetry attributes
        span = trace.get_current_span()
        if span:
            span.set_attribute("completion_count", counters['completion_count'])
            span.set_attribute("token_count", token_count)
            span.set_attribute("prompt_tokens", prompt_tokens)
            span.set_attribute("completion_tokens", completion_tokens)
            span.set_attribute("model", response.model)
            span.set_attribute("cost", cost)
            span.set_attribute("response", strResponse)
        return response
    return wrapper
# Monkey-patch the openai.Completion.create function
openai.Completion.create = count_completion_requests_and_tokens(openai.Completion.create)

通过将所有这些数据添加到我们的 Span 中,我们可以实际将其发送到我们的 OpenTelemetry OTLP 端点(在本例中,它将是 Elastic)。这样做的好处是,您可以轻松地使用这些数据进行搜索或构建仪表板和可视化效果。在最后一步中,我们还要计算成本。我们通过实现以下函数来完成此操作,该函数将计算对 OpenAI API 的单个请求的成本。

def calculate_cost(response):
    if response.model in ['gpt-4', 'gpt-4-0314']:
        cost = (response.usage.prompt_tokens * 0.03 + response.usage.completion_tokens * 0.06) / 1000
    elif response.model in ['gpt-4-32k', 'gpt-4-32k-0314']:
        cost = (response.usage.prompt_tokens * 0.06 + response.usage.completion_tokens * 0.12) / 1000
    elif 'gpt-3.5-turbo' in response.model:
        cost = response.usage.total_tokens * 0.002 / 1000
    elif 'davinci' in response.model:
        cost = response.usage.total_tokens * 0.02 / 1000
    elif 'curie' in response.model:
        cost = response.usage.total_tokens * 0.002 / 1000
    elif 'babbage' in response.model:
        cost = response.usage.total_tokens * 0.0005 / 1000
    elif 'ada' in response.model:
        cost = response.usage.total_tokens * 0.0004 / 1000
    else:
        cost = 0
    return cost

Elastic 来解救

一旦我们捕获了所有这些数据,就可以在 Elastic 中体验一些乐趣了。在 Discover 中,我们可以看到我们使用 OpenTelemetry 库发送的所有数据点

有了这些标签,就可以很容易地构建一个仪表板。看看我之前构建的这个 (它也已签入我的 GitHub 存储库)

我们还可以看到事务、OpenAI 服务的延迟以及与我们的 ChatGPT 服务调用相关的所有 span。

在事务视图中,我们还可以看到特定的 OpenAI 调用花费了多长时间

此处对 OpenAI 的某些请求花费了 3 秒以上。ChatGPT 的速度可能非常慢,因此对于我们来说,了解它的速度有多慢以及用户是否感到沮丧非常重要。

总结

我们研究了使用 OpenTelemetry 和 Elastic 监控 ChatGPT。ChatGPT 是一种世界性的现象,它无疑会不断增长和发展,很快每个人都会使用它。由于获取响应可能很慢,因此对于人们来说,能够了解使用此服务的任何代码的性能至关重要。

还有一个成本问题,因为了解这项服务是否正在侵蚀您的利润,以及您所要求的服务是否对您的业务有利可图至关重要。在当前的经济环境下,我们必须关注盈利能力。

请查看此解决方案的 代码。并且请随意使用“monitor”库来检测您自己的 OpenAI 代码。

有兴趣了解更多关于 Elastic Observability 的信息吗?请查看以下资源

并注册参加我们与 AWS 和 Forrester 合作的 Elastic Observability 趋势网络研讨会,不容错过!

在本篇博文中,我们可能使用了第三方生成式 AI 工具,这些工具由其各自的所有者拥有和运营。Elastic 对第三方工具没有任何控制权,并且我们对其内容、操作或使用,以及因您使用此类工具而可能造成的任何损失或损害概不负责。在使用包含个人、敏感或机密信息的 AI 工具时,请务必谨慎。您提交的任何数据都可能用于 AI 训练或其他目的。我们无法保证您提供的信息将被安全或保密。在使用任何生成式 AI 工具之前,您应熟悉其隐私实践和使用条款。

Elastic、Elasticsearch 和相关标记是 Elasticsearch N.V. 在美国和其他国家/地区的商标、徽标或注册商标。所有其他公司和产品名称均为其各自所有者的商标、徽标或注册商标。

分享这篇文章