产品评论服务

此服务负责返回产品评论,并根据产品描述和评论回答有关特定产品的问题。

它使用一个兼容 OpenAI 的 LLM 来回答终端用户关于特定产品的问题。

产品评论存储在数据库(PostgreSQL)中。

产品评论服务源代码

LLM 配置

默认情况下,此服务使用符合 OpenAI API 格式的模拟 LLM。通过在 .env.override 文件中填充以下环境变量,可以将其替换为实际的 OpenAI LLM。

LLM_BASE_URL=https://api.openai.com/v1
LLM_MODEL=gpt-4o-mini
OPENAI_API_KEY=<replace with API key>

自动仪表化

此基于 Python 的服务利用 OpenTelemetry 自动检测器(auto-instrumentor)来实现,这是通过利用 opentelemetry-instrument Python 包装器来运行脚本完成的。这可以在服务 DockerfileENTRYPOINT 命令中完成。

ENTRYPOINT [ "opentelemetry-instrument", "python", "product_reviews_server.py" ]

追踪

初始化追踪

OpenTelemetry SDK 在 __main__ 代码块中初始化。此代码将创建一个跟踪器提供程序(tracer provider),并建立一个 Span Processor 来使用。导出终结点、资源属性和服务名称会根据环境变量由 OpenTelemetry 自动检测器自动设置。

tracer = trace.get_tracer_provider().get_tracer("product-reviews")

为自动仪表化的 Span 添加属性

在自动仪表化代码的执行过程中,您可以从上下文中获取当前的 Span。

span = trace.get_current_span()

通过使用 Span 对象上的 set_attribute 来添加属性到 Span。在 get_product_reviews 函数中,会向 Span 添加一个属性来捕获请求中传递的产品 ID。

span.set_attribute("app.product.id", request_product_id)

创建新跨度

可以使用 OpenTelemetry Tracer 对象中的 start_as_current_span 来创建新的 Span 并将其放入活动上下文中。当与 with 块结合使用时,Span 会在块结束执行时自动结束。这在 get_product_reviews 函数中完成。

with tracer.start_as_current_span("get_product_reviews") as span:

指标

初始化指标

OpenTelemetry SDK 在 __main__ 代码块中初始化。此代码将创建一个 Meter Provider。导出终结点、资源属性和服务名称会根据环境变量由 OpenTelemetry 自动检测器自动设置。

meter = metrics.get_meter_provider().get_meter("product-reviews")

自定义指标

目前提供以下自定义指标

  • app_product_review_counter: 服务返回的产品评论数量的累积计数。
  • app_ai_assistant_counter: 发送到产品 AI 助手(product AI Assistant)的总问题数量的累积计数。

自动检测的指标

以下指标通过自动检测器提供,这是 opentelemetry-instrumentation-system-metrics 的功劳,该库在构建产品评论服务 Docker 镜像时作为 opentelemetry-bootstrap 的一部分安装。

  • runtime.cpython.cpu_time
  • runtime.cpython.memory
  • runtime.cpython.gc_count

日志

初始化日志

OpenTelemetry SDK 在 __main__ 代码块中初始化。以下代码创建一个具有批处理处理器(batch processor)、OTLP 日志导出器(exporter)和日志处理程序(handler)的日志提供程序(logger provider)。最后,它创建一个供应用程序使用的日志记录器(logger)。

logger_provider = LoggerProvider(
    resource=Resource.create(
        {
            'service.name': service_name,
        }
    ),
)
set_logger_provider(logger_provider)
log_exporter = OTLPLogExporter(insecure=True)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider)

logger = logging.getLogger('main')
logger.addHandler(handler)

创建日志记录

使用日志记录器创建日志。可以在 get_ai_assistant_response 函数中找到示例。

logger.info(f"Model wants to call {len(tool_calls)} tool(s)")

如您所见,初始化后,日志记录的创建方式与标准 Python 相同。OpenTelemetry 库会自动为每个日志记录添加跟踪 ID 和 Span ID,从而能够关联日志和跟踪。

备注

Python 的日志功能仍处于实验阶段,可能会有一些变更。本服务中的实现遵循 Python 日志示例