在这里插入图片描述

  【个人主页:玄同765

大语言模型(LLM)开发工程师中国传媒大学·数字媒体技术(智能交互与游戏设计)

深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调

技术栈:Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️

工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案 

      

专栏传送门:LLM大模型开发 项目实战指南Python 从真零基础到纯文本 LLM 全栈实战​​​​​从零学 SQL + 大模型应用落地大模型开发小白专属:从 0 入门 Linux&Shell

     

「让AI交互更智能,让技术落地更高效」

欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!

在 LLM(大模型)应用开发中,日志是定位问题、优化性能、保障系统稳定的核心工具。但传统 Python logging 模块的繁琐配置、异步场景下的日志阻塞、异常堆栈的不完整记录,常常让开发者在日志配置上花费大量时间,而无法专注于 LLM 业务逻辑。

Loguru 作为一款 “开箱即用” 的 Python 日志库,凭借其极简配置、自动格式化、异步支持、异常捕获等特性,完美解决了 LLM 开发中的日志痛点。本文将从核心特性、安装配置、LLM 实战场景、最佳实践四个维度,带你掌握 Loguru 在 LLM 开发中的正确打开方式。


一、Loguru 核心特性:为什么适合 LLM 开发?

Loguru 的设计理念是 “让日志变得简单”,其核心特性完美适配 LLM 开发的复杂场景:

1. 开箱即用,零配置启动

无需繁琐的logging.basicConfig配置,导入即可直接使用,适合 LLM 原型开发快速验证:

from loguru import logger

logger.info("LLM应用启动成功")  # 直接输出带时间、级别、模块的格式化日志

2. 自动格式化与着色

默认输出包含时间戳、日志级别、模块名、行号的结构化日志,终端输出自动着色,便于快速定位 LLM 请求的错误位置:

2024-05-20 14:30:00 | INFO     | __main__:chat:12 - LLM请求成功,模型:gpt-3.5-turbo,耗时:1.2s
2024-05-20 14:30:05 | ERROR    | __main__:chat:15 - LLM请求失败,错误:API超时

3. 原生异步支持

完美兼容 FastAPI、Asyncio 等异步框架,无需额外配置即可处理高并发 LLM 请求的日志,避免阻塞事件循环:

import asyncio
from loguru import logger

async def llm_chat(prompt: str):
    logger.info(f"异步LLM请求: {prompt[:50]}...")
    # 模拟异步调用LLM API
    await asyncio.sleep(1)
    logger.success("异步LLM请求完成")

4. 全局异常捕获

自动捕获整个应用的未处理异常,记录完整堆栈信息,包括 LLM 调用的上下文(如请求参数、模型名称),大幅降低问题定位难度:

from loguru import logger

# 全局捕获未处理异常
logger.add("llm_errors.log", level="ERROR", backtrace=True, diagnose=True)

def llm_call(prompt: str):
    # 模拟LLM调用中的异常
    raise ValueError("模型返回格式异常")

llm_call("生成一篇技术博客")  # 异常会自动记录到日志文件,包含完整堆栈

5. 灵活的日志轮转与归档

支持按文件大小、时间、行数自动轮转日志,自动压缩归档旧日志,适合长期运行的 LLM 应用(如企业级助手、API 网关):

from loguru import logger

# 按大小轮转:单个日志文件最大100MB,保留5个备份,自动压缩
logger.add("llm_app.log", rotation="100 MB", retention=5, compression="zip")

# 按时间轮转:每天0点生成新日志,保留30天
logger.add("llm_daily.log", rotation="00:00", retention="30 days")

6. 多目标输出与过滤

支持同时输出到控制台、文件、邮件、甚至第三方服务(如 Sentry),并可通过过滤器实现 LLM 场景的日志隔离(如按模型名称分开记录):

from loguru import logger

# 同时输出到控制台和文件
logger.add("llm_app.log", level="INFO")

# 仅记录gpt-4模型的日志到单独文件
logger.add("llm_gpt4.log", filter=lambda record: "gpt-4" in record["extra"].get("model", ""))

二、安装与基础配置:5 分钟搞定 LLM 日志

1. 安装 Loguru

pip install loguru

2. 基础配置:LLM 场景定制

Loguru 的配置通过logger.add()实现,以下是 LLM 开发中常用的基础配置:

from loguru import logger
import sys

# 移除默认控制台输出(可选)
logger.remove()

# 配置控制台输出:定制LLM场景的日志格式
logger.add(
    sys.stderr,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | <level>{message}</level> | 模型:{extra[model]} | 请求ID:{extra[request_id]}",
    level="INFO",
    colorize=True
)

# 配置文件输出:记录完整日志,包含异常堆栈
logger.add(
    "llm_app.log",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} | {message} | 模型:{extra[model]} | 请求ID:{extra[request_id]}",
    level="DEBUG",
    rotation="100 MB",
    retention=10,
    compression="zip",
    backtrace=True,  # 记录完整异常堆栈
    diagnose=True   # 记录变量值(生产环境建议关闭)
)

3. LLM 场景扩展:绑定上下文信息

通过logger.bind()绑定 LLM 请求的上下文信息(如模型名称、请求 ID),实现日志的全链路追踪:

# 绑定上下文:每个LLM请求生成唯一请求ID
import uuid
llm_logger = logger.bind(model="gpt-3.5-turbo", request_id=str(uuid.uuid4()))

llm_logger.info("LLM请求开始,prompt:生成一篇关于Loguru的技术博客")
# 输出:2024-05-20 15:00:00 | INFO     | __main__:<module>:1 | LLM请求开始,prompt:生成一篇关于Loguru的技术博客 | 模型:gpt-3.5-turbo | 请求ID:xxxx-xxxx-xxxx

三、LLM 开发实战:Loguru 的核心应用场景

1. 场景 1:LLM API 调用日志记录

在调用 OpenAI、Claude 等大模型 API 时,用 Loguru 记录请求参数、响应状态、耗时等关键信息:

from loguru import logger
import openai
import time
import uuid

# 绑定上下文
def get_llm_logger(model: str):
    return logger.bind(model=model, request_id=str(uuid.uuid4()))

def call_openai(prompt: str, model: str = "gpt-3.5-turbo"):
    llm_logger = get_llm_logger(model)
    start_time = time.time()
    try:
        llm_logger.info(f"LLM请求开始,prompt:{prompt[:50]}...")
        response = openai.ChatCompletion.create(
            model=model,
            messages=[{"role": "user", "content": prompt}]
        )
        llm_logger.success(f"LLM请求完成,耗时:{time.time()-start_time:.2f}s,token使用量:{response['usage']['total_tokens']}")
        return response["choices"][0]["message"]["content"]
    except Exception as e:
        llm_logger.error(f"LLM请求失败,错误:{str(e)}", exc_info=True)  # exc_info=True记录异常堆栈
        raise

# 调用示例
call_openai("生成一篇关于Python日志库Loguru的技术博客")

2. 场景 2:异步 LLM 接口日志处理

在 FastAPI 等异步框架中,Loguru 原生支持异步日志,避免阻塞事件循环:

from fastapi import FastAPI, Request
from loguru import logger
import openai
import time
import uuid

app = FastAPI(title="LLM API")

# 中间件:为每个请求绑定请求ID
@app.middleware("http")
async def add_request_id(request: Request, call_next):
    request_id = str(uuid.uuid4())
    response = await call_next(request)
    response.headers["X-Request-ID"] = request_id
    # 绑定请求ID到全局日志
    logger.configure(extra={"request_id": request_id})
    return response

@app.post("/api/chat")
async def chat(prompt: str, model: str = "gpt-3.5-turbo"):
    start_time = time.time()
    logger.info(f"异步LLM请求开始,prompt:{prompt[:50]}...,模型:{model}")
    try:
        # 异步调用OpenAI API(需安装aiohttp版本的openai)
        # response = await openai.ChatCompletion.acreate(model=model, messages=[{"role": "user", "content": prompt}])
        await asyncio.sleep(1)  # 模拟异步调用
        logger.success(f"异步LLM请求完成,耗时:{time.time()-start_time:.2f}s")
        return {"response": "模拟LLM响应", "request_id": logger.extra["request_id"]}
    except Exception as e:
        logger.error(f"异步LLM请求失败,错误:{str(e)}", exc_info=True)
        raise

3. 场景 3:异常捕获与错误追踪

Loguru 的logger.catch()装饰器可以自动捕获函数中的异常并记录,适合 LLM 应用中的工具函数:

from loguru import logger

@logger.catch  # 自动捕获函数中的异常并记录
def llm_tool_function(prompt: str):
    # 模拟工具函数中的异常
    if not prompt:
        raise ValueError("prompt不能为空")
    return f"处理后的prompt:{prompt}"

# 调用示例:异常会自动记录到日志
llm_tool_function("")

4. 场景 4:JSON 格式日志:便于 LLM 日志分析

将日志输出为 JSON 格式,方便后续用 ELK、Datadog 等工具分析 LLM 请求的性能、错误率等指标:

from loguru import logger
import json

# 自定义JSON格式化函数
def json_formatter(record):
    record["extra"]["message"] = record["message"]
    return json.dumps(record["extra"]) + "\n"

# 配置JSON格式日志输出
logger.add(
    "llm_app.json.log",
    format=json_formatter,
    level="INFO",
    rotation="100 MB"
)

# 绑定上下文信息
logger.bind(model="gpt-3.5-turbo", request_id="xxxx-xxxx", user_id="user123").info("LLM请求开始")
# 输出JSON:{"model": "gpt-3.5-turbo", "request_id": "xxxx-xxxx", "user_id": "user123", "message": "LLM请求开始"}

四、LLM 开发中的 Loguru 最佳实践

1. 日志脱敏:保护敏感信息

LLM 应用中常常处理用户的敏感 prompt(如个人信息、企业机密),需在日志中脱敏处理:

from loguru import logger
import re

# 脱敏函数:替换手机号、邮箱
def sensitive_data_masking(message: str):
    message = re.sub(r'1[3-9]\d{9}', '1*********', message)
    message = re.sub(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', '***@***.com', message)
    return message

# 配置日志过滤器
logger.add(
    "llm_app.log",
    filter=lambda record: record["message"] != sensitive_data_masking(record["message"]),
    format="{time} | {level} | " + sensitive_data_masking("{message}")
)

2. 按 LLM 模型隔离日志

通过logger.bind()和过滤器,将不同模型的日志分开记录,便于后续分析各模型的性能:

from loguru import logger

# 记录所有模型的日志
logger.add("llm_all.log", level="INFO")

# 仅记录gpt-4模型的日志
logger.add("llm_gpt4.log", filter=lambda record: record["extra"].get("model") == "gpt-4")

# 仅记录claude-3模型的日志
logger.add("llm_claude3.log", filter=lambda record: record["extra"].get("model") == "claude-3")

# 调用时绑定模型信息
logger.bind(model="gpt-4").info("gpt-4请求开始")
logger.bind(model="claude-3").info("claude-3请求开始")

3. 结合请求 ID 实现全链路追踪

为每个 LLM 请求生成唯一请求 ID,绑定到日志中,便于追踪整个请求的日志流程:

from loguru import logger
import uuid

def llm_request(prompt: str, model: str):
    request_id = str(uuid.uuid4())
    # 绑定请求ID
    llm_logger = logger.bind(request_id=request_id, model=model)
    llm_logger.info(f"请求开始,prompt:{prompt[:50]}...")
    try:
        # 调用LLM API
        llm_logger.success("请求完成")
        return {"response": "模拟响应", "request_id": request_id}
    except Exception as e:
        llm_logger.error(f"请求失败,错误:{str(e)}")
        raise

4. 生产环境配置建议

生产环境中需关闭diagnose=True(避免泄露敏感变量值),并配置邮件 / 告警通知:

from loguru import logger

# 生产环境日志配置
logger.add(
    "llm_app.log",
    level="INFO",
    rotation="100 MB",
    retention=30,
    compression="zip",
    backtrace=True,
    diagnose=False  # 生产环境关闭变量诊断
)

# 错误日志发送邮件(需安装smtplib)
logger.add(
    "mailto:admin@example.com",
    level="ERROR",
    format="{time} | {level} | {message} | {extra}",
    subject="LLM应用错误告警"
)

五、Loguru vs 传统 logging:LLM 开发中的效率对比

维度 Loguru 传统 logging
配置复杂度 零配置启动,5 分钟搞定 LLM 日志 需编写大量配置代码,学习成本高
异步支持 原生支持异步日志,适配高并发 LLM 请求 需手动配置异步 Handler,易阻塞事件循环
异常捕获 自动捕获未处理异常,记录完整堆栈 需手动 try-except,堆栈记录繁琐
日志格式定制 简洁的格式化字符串,支持上下文变量 需编写 Formatter 类,代码繁琐
日志轮转与归档 一行代码实现自动轮转与压缩 需配置 RotatingFileHandler 等,代码复杂
LLM 场景适配 天然支持上下文绑定、多模型日志隔离 需自定义过滤器和额外代码实现

六、总结:Loguru 让 LLM 开发更专注业务

在 LLM 开发中,Loguru 凭借其开箱即用、异步支持、异常自动捕获、灵活配置等特性,完美解决了传统日志库的痛点,让开发者从繁琐的日志配置中解放出来,专注于 LLM 业务逻辑的实现。

无论是快速原型开发、高并发 API 网关,还是企业级 LLM 助手,Loguru 都能提供简单高效的日志解决方案。从今天起,让 Loguru 成为你 LLM 开发中的日志神器,让日志配置从此无痛!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐