Xử lý lỗi và theo dõi quá trình phát triển LLM

Xử lý lỗi và theo dõi quá trình phát triển LLM

Trong bài viết này, chúng ta sẽ thảo luận về hai vấn đề thực tế khi làm việc với mô hình ngôn ngữ lớn (LLM). Đầu tiên, cách xử lý các lỗi có thể xảy ra khi gọi API OpenAI. Thứ hai, cách sử dụng các công cụ ghi nhật ký để giám sát quá trình chạy ứng dụng LLM.

Xử lý lỗi khi sử dụng API OpenAI

Khi tương tác với API OpenAI, bạn có thể gặp nhiều loại lỗi khác nhau. Hiểu cách xử lý các lỗi này rất quan trọng để đảm bảo tính ổn định và đáng tin cậy của ứng dụng. Nếu biết trước các loại lỗi có thể xảy ra, bạn sẽ có cách xử lý phù hợp.

Dưới đây là tổng hợp các loại lỗi phổ biến mà API OpenAI có thể trả về, cùng với các mẹo xử lý chúng:

  1. Lỗi yêu cầu (400): Yêu cầu không đúng định dạng hoặc thiếu tham số bắt buộc như Token hoặc đầu vào. Nguyên nhân thường do tên tham số, loại dữ liệu, giá trị hoặc định dạng không khớp với tài liệu.
  2. Lỗi xác thực (401): API key không hợp lệ, đã hết hạn hoặc bị thu hồi. Nguyên nhân có thể do API key sai hoặc có vấn đề bảo mật.
  3. Lỗi giới hạn tốc độ (429): Gửi quá nhiều Token hoặc yêu cầu trong một khoảng thời gian, vượt quá giới hạn tốc độ được cấp phát.
  4. Lỗi máy chủ (500): Máy chủ gặp lỗi không mong muốn khi xử lý yêu cầu, có thể do lỗi tạm thời, bug hoặc gián đoạn hệ thống.
  5. Lỗi kết nối: Yêu cầu không thể đến máy chủ hoặc thiết lập kết nối an toàn, có thể do vấn đề mạng, cấu hình proxy, chứng chỉ SSL hoặc quy tắc tường lửa.
  6. Lỗi thời gian chờ (timeout): Yêu cầu mất quá nhiều thời gian để hoàn thành, máy chủ đã đóng kết nối. Có thể do vấn đề mạng, máy chủ quá tải hoặc yêu cầu quá phức tạp.

Khi gặp lỗi, bạn cần kiểm tra API key trước tiên. Nếu gặp vấn đề kết nối, có thể cần chuyển mạng hoặc điều chỉnh cài đặt proxy. Với lỗi giới hạn tốc độ, giảm tần suất yêu cầu hoặc đợi đến khi giới hạn được reset. Khi gặp lỗi máy chủ, hãy đợi vài giây rồi thử lại yêu cầu. Kiểm tra trang trạng thái hệ thống OpenAI để biết có sự kiện hoặc bảo trì nào đang diễn ra ảnh hưởng đến dịch vụ.

Ví dụ dưới đây minh họa một lỗi khi gọi API OpenAI. Chương trình này cố gắng yêu cầu GPT tổng hợp nội dung từ tất cả các tài liệu Markdown trong một thư mục cụ thể và tạo một tài liệu mới.


import os

# Khởi tạo client OpenAI
from openai import OpenAI 
ai_client = OpenAI()

input_folder = 'data/markdown_files'
output_file = 'data/summary/combined_summary.md'

def collect_markdown_files(folder_path):
    file_contents = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.md'):
            with open(os.path.join(folder_path, file_name), 'r', encoding='utf-8') as file:
                file_contents.append(file.read())
    return file_contents

def generate_summary_with_model(content_list):
    combined_content = "\n\n".join(content_list)
    response = ai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "Bạn đang tạo bản tóm tắt tài liệu. Hãy cung cấp bản tóm tắt định dạng Markdown."},
            {"role": "user", "content": [
                "Nội dung các tài liệu:",
                {"type": "text", "text": combined_content}
            ]}
        ],
        temperature=0.5,
    )
    return response.choices[0].message.content

def save_summary_to_file(summary, destination):
    with open(destination, 'w', encoding='utf-8') as file:
        file.write(summary)

def execute_main_task():
    markdown_contents = collect_markdown_files(input_folder)
    summary_result = generate_summary_with_model(markdown_contents)
    save_summary_to_file(summary_result, output_file)
    print(f"Tài liệu tóm tắt đã được tạo tại {output_file}")

if __name__ == "__main__":
    execute_main_task()

Chạy chương trình sẽ tạo ra lỗi:

openai.BadRequestError: Error code: 400 - {'error': {'message': "Invalid type for 'messages[1].content[0]': expected an object, but got a string instead.", 'type': 'invalid_request_error', 'param': 'messages[1].content[0]', 'code': 'invalid_type'}}

Bây giờ, chúng ta điều chỉnh chương trình bằng cách thêm khối try/except để xử lý lỗi từ API OpenAI:


def generate_summary_with_model(content_list):
    try:
        response = ai_client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "system", "content": "Bạn đang tạo bản tóm tắt tài liệu. Hãy cung cấp bản tóm tắt định dạng Markdown."},
                {"role": "user", "content": [
                    "Nội dung các tài liệu:",
                    {"type": "text", "text": "\n\n".join(content_list)}
                ]}
            ],
            temperature=0.5,
        )
        return response.choices[0].message.content
    except Exception as error:
        print(f"Lỗi khi tạo tóm tắt: {error}")
        return None

Thực tế, vấn đề nằm ở việc xây dựng tham số messages, cố gắng chèn một danh sách vào trường content trong khi trường này mong đợi một chuỗi. Để giải quyết vấn đề này, chúng ta cần kết hợp nội dung thành một chuỗi duy nhất thay vì danh sách.

Sử dụng Weights & Biases để theo dõi quá trình phát triển

Weights & Biases (wandb) là một công cụ phổ biến trong lĩnh vực học máy và AI, đặc biệt hữu ích cho các công việc liên quan đến dữ liệu lớn và gỡ lỗi mô hình. Đây là công cụ theo dõi thí nghiệm và trực quan hóa dành cho các dự án học máy và học sâu, tự động ghi lại và theo dõi các thông số thí nghiệm, siêu tham số, kiến trúc mô hình và chỉ số huấn luyện.

Đối với việc phát triển ứng dụng LLM, dù chúng ta không cần huấn luyện mô hình, nhưng vẫn có thể tận dụng khả năng ghi nhật ký, theo dõi và trực quan hóa mạnh mẽ của wandb để giám sát trạng thái chạy ứng dụng LLM. Ví dụ, khi yêu cầu mô hình tóm tắt 100 tài liệu, chúng ta có thể ghi lại kích thước mỗi tài liệu, số Token truyền đi, độ dài văn bản sau khi tóm tắt, v.v.

Đầu tiên, cài đặt gói wandb:


pip install wandb

Tạo tài khoản trên trang web của wandb và lấy API Key để sử dụng trong chương trình.

Chúng ta sẽ cải tiến chương trình tóm tắt tài liệu để ghi lại các chi tiết như tên tệp, độ dài tóm tắt, v.v.:


def collect_markdown_files(folder_path):
    file_contents = []
    file_names = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.md'):
            with open(os.path.join(folder_path, file_name), 'r', encoding='utf-8') as file:
                file_contents.append(file.read())
                file_names.append(file_name)
    return file_contents, file_names

def execute_main_task():
    # Khởi tạo phiên làm việc wandb
    wandb.init(project="document_summarization", name="markdown_processing")

    markdown_contents, file_names = collect_markdown_files(input_folder)
    all_summaries = []

    for content, name in zip(markdown_contents, file_names):
        try:
            summary = generate_summary_with_model(content)
            all_summaries.append(f"# Tóm tắt {name}\n\n{summary}\n\n")
            wandb.log({"file_name": name, "summary_length": len(summary)})

        except Exception as error:
            print(f"Lỗi khi tóm tắt {name}: {error}")
            wandb.log({"file_name": name, "error": str(error)})

    final_summary = "\n".join(all_summaries)
    save_summary_to_file(final_summary, output_file)
    print(f"Tài liệu tóm tắt đã được tạo tại {output_file}")
    wandb.finish()

Cấu trúc chương trình như sau:

  1. Khởi tạo phiên làm việc wandb với thông số dự án và tên.
  2. Xử lý từng tệp Markdown, gọi hàm generate_summary_with_model để tạo tóm tắt.
  3. Ghi lại trạng thái và độ dài tóm tắt của mỗi tệp bằng wandb.log. Đồng thời, bắt ngoại lệ và ghi thông tin lỗi.
  4. Kết hợp tất cả các tóm tắt thành một tệp duy nhất và ghi ra tệp đầu ra.

Sử dụng LangSmith để giám sát cuộc gọi LLM

Đối với việc phát triển ứng dụng LLM, Weights & Biases chưa đủ hoàn hảo vì một số chi tiết như đầu vào/đầu ra của mô hình, số Token sử dụng, chi phí phát sinh không được tự động tổng hợp. Lúc này, LangSmith - một công cụ trong hệ sinh thái LangChain - sẽ giúp ích. LangSmith là nền tảng để xây dựng các ứng dụng LLM cấp sản xuất, giúp bạn giám sát và đánh giá ứng dụng chặt chẽ, và có thể sử dụng độc lập không phụ thuộc vào LangChain.

Trước tiên, cài đặt LangSmith:


pip install -U langsmith

Tạo API Key trên trang cài đặt của LangSmith và đặt biến môi trường:


export LANGCHAIN_TRACING_V2=true 
export LANGCHAIN_API_KEY=

Bây giờ, chúng ta có thể sử dụng LangSmith để ghi lại quá trình gọi LLM. Dưới đây là chương trình sử dụng decorator @traceable để tự động theo dõi các cuộc gọi LLM:


from dotenv import load_dotenv
load_dotenv()
import os
import openai
from langsmith.wrappers import wrap_openai
from langsmith import traceable

# Tạo client OpenAI và gói với langsmith để theo dõi
openai_client = wrap_openai(openai.Client())

input_folder = 'data/markdown_files'
output_file = 'data/summary/combined_summary.md'

def collect_markdown_files(folder_path):
    file_contents = []
    file_names = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.md'):
            with open(os.path.join(folder_path, file_name), 'r', encoding='utf-8') as file:
                file_contents.append(file.read())
                file_names.append(file_name)
    return file_contents, file_names

@traceable
def generate_summary_with_model(content):
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "Bạn đang tạo bản tóm tắt tài liệu. Hãy cung cấp bản tóm tắt định dạng Markdown."},
            {"role": "user", "content": "Nội dung tài liệu:\n\n" + content}
        ],
        temperature=0.5,
    )
    return response.choices[0].message.content

def save_summary_to_file(summary, destination):
    with open(destination, 'w', encoding='utf-8') as file:
        file.write(summary)

def execute_main_task():
    markdown_contents, file_names = collect_markdown_files(input_folder)
    all_summaries = []

    for content, name in zip(markdown_contents, file_names):
        try:
            summary = generate_summary_with_model(content)
            all_summaries.append(f"# Tóm tắt {name}\n\n{summary}\n\n")
            # Ghi nhật ký bằng langsmith
            print(f"Độ dài tóm tắt cho {name}: {len(summary)}")

        except Exception as error:
            print(f"Lỗi khi tóm tắt {name}: {error}")
            # Ghi nhật ký lỗi bằng langsmith
            print(f"Lỗi: {str(error)}")

    final_summary = "\n".join(all_summaries)
    save_summary_to_file(final_summary, output_file)
    print(f"Tài liệu tóm tắt đã được tạo tại {output_file}")

if __name__ == "__main__":
    execute_main_task()

Trong mã nguồn, chúng ta gói client OpenAI bằng LangSmith để theo dõi và ghi nhật ký. Hàm wrap_openai dùng để gói client OpenAI thành client tương thích với LangSmith. Sau đó, thêm decorator @traceable để đánh dấu hàm có thể theo dõi, cho phép LangSmith ghi lại đầu vào và đầu ra của hàm.

Sau khi chạy chương trình, đăng nhập vào LangSmith, bạn sẽ thấy các chi tiết tương tác giữa chương trình và mô hình đều được ghi lại.

Tổng kết

Khi gọi API OpenAI, các loại lỗi phổ biến bao gồm lỗi yêu cầu (400), lỗi xác thực (401), lỗi giới hạn tốc độ (429), lỗi máy chủ (500), lỗi kết nối và lỗi thời gian chờ. Để xử lý các lỗi này, chúng ta có thể kiểm tra API key, điều chỉnh cài đặt mạng, giảm tần suất yêu cầu, thử lại yêu cầu, v.v.

Để giám sát và ghi nhật ký quá trình chạy ứng dụng LLM, chúng ta có thể sử dụng các công cụ như Weights & Biases và LangSmith. Weights & Biases phù hợp để ghi lại và trực quan hóa các thông số và chỉ số trong quá trình huấn luyện, trong khi LangSmith更适合追踪 chi tiết cuộc gọi LLM, bao gồm đầu vào/đầu ra, số lần gọi, số Token sử dụng, v.v.

Ngoài Weights & Biases, TensorBoard cũng là công cụ trực quan hóa học máy phổ biến, đặc biệt để giám sát và ghi lại các chỉ số, kiến trúc mô hình và đồ thị luồng dữ liệu trong quá trình huấn luyện mô hình dựa trên TensorFlow. Một nền tảng giám sát học máy mã nguồn mở khác là MLflow, dùng để quản lý vòng đời học máy, bao gồm theo dõi thí nghiệm, quản lý dự án, quản lý mô hình và triển khai. Hai công cụ này cũng đáng để bạn tìm hiểu.

Thẻ: LLM OpenAI API Weights & Biases LangSmith Xử lý lỗi

Đăng vào ngày 20 tháng 6 lúc 23:36