如何快速修復「OpenAI API Token 限制」問題:2025 年完整指南

Kelly Allemanon 2 months ago

Visit Nudemaker AI\n\n## 引言:掌握 OpenAI API Token 限制

歡迎閱讀這份權威指南,旨在解決開發人員在使用 OpenAI 強大 API 時最常見且往往最令人沮喪的問題之一:「Token 限制」錯誤。無論您是開發複雜的 AI 應用程式、自動化內容生成,還是將大型語言模型整合到您的工作流程中,遇到 Token 限制都可能阻礙進度、降低用戶體驗,甚至產生意料之外的成本。

這份綜合指南專為希望理解、預防並迅速解決 OpenAI API Token 限制問題的開發人員、資料科學家和 AI 愛好者設計。我們將深入探討實用策略、程式碼層面的優化和架構考量,以確保您的應用程式順暢、高效且在預算內運行。讀完本指南後,您將掌握專業管理 Token 消耗的知識和工具,確保您的 AI 專案蓬勃發展。

什麼是 Token 限制?

在我們深入探討解決方案之前,讓我們先簡要闡明在 OpenAI 模型中「Token」的含義。Token 可以被視為單詞的一部分。對於英文文本,1 個 Token 大約是 4 個字元或 ¾ 個單詞。OpenAI 模型透過將文本分解為這些 Token 來處理文本。Token 限制指的是您在單次 API 請求(輸入 + 輸出)中可以發送的最大 Token 數量,或您在一段時間內可以發送 Token 的最大速率(每分鐘 Token 數,TPM)。

超出這些限制會導致 API 錯誤,通常表示請求過大或已達到您的速率限制。本指南將重點關注「每個請求的總 Token 數」限制和「速率限制」(每分鐘 Token 數/每分鐘請求數)。

先決條件

為了有效地遵循本指南,您應該具備:

  • 一個 OpenAI API 帳戶: 能夠訪問 OpenAI 平台和 API 金鑰。
  • 基本的程式設計知識: 熟悉 Python(或您偏好的語言),因為大多數範例將使用 Python。
  • 對 API 呼叫的理解: 關於如何發送 API 請求的基本知識。
  • 已安裝 OpenAI Python 函式庫: pip install openai

如何快速修復「OpenAI API Token 限制」問題:2025 年逐步指南

修復 Token 限制問題需要多方面的方法,結合主動設計選擇和被動故障排除。以下是系統性的分解:

步驟 1:了解您目前的 Token 用量和限制

解決問題的第一步是了解其範圍。您需要知道您目前的限制是什麼,以及您距離它們有多近。

1.1 識別您的 OpenAI 等級和速率限制

OpenAI 根據您的使用等級和付款歷史記錄施加不同的速率限制。新帳戶通常以較低的限制開始。

  • 檢查您的用量儀表板:

    • 登入您的 OpenAI 帳戶。
    • 導航至「用量」或「速率限制」部分(通常在左側邊欄的「設定」或「API 金鑰」下)。
    • 在這裡,您將看到不同模型(例如 gpt-3.5-turbogpt-4)的當前速率限制,以每分鐘請求數 (RPM) 和每分鐘 Token 數 (TPM) 表示。
  • 了解不同的限制:

    • 上下文視窗限制: 這是單次 API 呼叫中允許的最大 Token 數(輸入 + 輸出)。對於 gpt-3.5-turbo,通常是 4096 或 16385 Token,而 gpt-4 根據版本不同可以有 8k、32k 甚至 128k Token。達到此限制意味著您的提示過長。
    • 速率限制 (RPM/TPM): 這些限制控制您在所有 API 呼叫中一分鐘內可以發送多少請求或 Token。達到此限制意味著您發送請求的速度過快。

1.2 在發送請求前監控 Token 數量

在將輸入提示發送到 API 之前,主動計算其 Token 數量。這使您可以在必要時截斷或總結。

  • 使用 tiktoken 函式庫: OpenAI 提供 tiktoken 函式庫正是為此目的。

    import tiktoken
    
    def num_tokens_from_string(string: str, model_name: str) -> int:
        """Returns the number of tokens in a text string for a given model."""
        encoding = tiktoken.encoding_for_model(model_name)
        num_tokens = len(encoding.encode(string))
        return num_tokens
    
    # Example Usage:
    text_to_send = "This is a very long piece of text that we want to send to the OpenAI API."
    model_id = "gpt-3.5-turbo" # Or "gpt-4", "text-davinci-003", etc.
    tokens = num_tokens_from_string(text_to_send, model_id)
    print(f"The text has {tokens} tokens.")
    
    # For chat completions, you need to account for system/user/assistant roles
    def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613"):
        """Return the number of tokens used by a list of messages."""
        try:
            encoding = tiktoken.encoding_for_model(model)
        except KeyError:
            print("Warning: model not found. Using cl100k_base encoding.")
            encoding = tiktoken.get_encoding("cl100k_base")
        if model in {
            "gpt-3.5-turbo-0613",
            "gpt-3.5-turbo-16k-0613",
            "gpt-4-0613",
            "gpt-4-32k-0613",
        }:
            tokens_per_message = 3
            tokens_per_name = 1
        elif model == "gpt-3.5-turbo-0301":
            tokens_per_message = 4  # every message follows <|start|>user<|end|>
            tokens_per_name = -1  # no name is expected
        elif "gpt-3.5-turbo" in model:
            print("Warning: gpt-3.5-turbo may update over time. Relying on gpt-3.5-turbo-0613 token counts is recommended.")
            return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613")
        elif "gpt-4" in model:
            print("Warning: gpt-4 may update over time. Relying on gpt-4-0613 token counts is recommended.")
            return num_tokens_from_messages(messages, model="gpt-4-0613")
        else:
            raise NotImplementedError(
                f"""num_tokens_from_messages() is not implemented for model {model}. 
                See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens."""
            )
        num_tokens = 0
        for message in messages:
            num_tokens += tokens_per_message
            for key, value in message.items():
                num_tokens += len(encoding.encode(value))
                if key == "name":
                    num_tokens += tokens_per_name
        num_tokens += 3  # every reply is primed with <|start|>assistant<|end|>
        return num_tokens
    
    messages = [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What is the capital of France?"},
    ]
    tokens_chat = num_tokens_from_messages(messages, model="gpt-3.5-turbo")
    print(f"The chat messages have {tokens_chat} tokens.")
    

步驟 2:優化您的提示和輸入資料

避免 Token 限制最直接的方法是減少您發送的 Token 數量。

2.1 總結和濃縮

  • 預處理大型文本: 如果您要輸入長篇文件,請考慮在將其發送到 API 之前 進行總結。您可以使用另一個更便宜或更快的模型(例如,較小的 gpt-3.5-turbo 呼叫,甚至是本地摘要模型)來提取資訊。
  • 提取關鍵資訊: 不要發送整篇文章,只提取特定查詢所需的相關段落或資料點。
  • 消除冗餘: 從您的提示中刪除重複的短語、不必要的問候語或過於冗長的說明。

2.2 有效的提示工程

  • 簡潔明瞭: 直入主題。每個字詞都很重要。

  • 謹慎使用範例: 雖然範例對於少樣本學習很有好處,但只使用最具說服力的範例。

  • 指定輸出格式: 引導模型產生特定、最小的輸出格式(例如,JSON、單一句子)可以減少輸出 Token。

    # Bad (verbose output likely)
    response = openai.Completion.create(
        model="text-davinci-003",
        prompt="Tell me about the history of the internet.",
        max_tokens=1000
    )
    
    # Good (concise output expected)
    response = openai.Completion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a concise historical summarizer."},
            {"role": "user", "content": "Summarize the key milestones in the history of the internet in 3 bullet points."},
        ],
        max_tokens=200 # Set a reasonable max_tokens for output
    )
    

2.3 管理對話歷史記錄(聊天模型)

對於對話式 AI,messages 陣列會迅速增長,消耗 Token。

  • 滑動視窗: 只保留對話中最新的 N 輪。當對話超過一定 Token 數量時,刪除最舊的訊息。
  • 總結過去的回合: 定期總結對話歷史記錄,並將摘要注入系統訊息中,有效地「壓縮」過去的內容。
  • 混合方法: 使用滑動視窗,但將最舊的已刪除訊息總結為「上下文」訊息。

步驟 3:實施速率限制處理和重試

即使使用優化的提示,您也可能在高峰使用或高並發期間達到速率限制 (TPM/RPM)。健壯的應用程式需要優雅地處理這些情況。

3.1 指數退避和重試

當您收到 RateLimitError (HTTP 429) 時,您不應該立即重試。相反,在重試之前等待越來越長的時間。

  • 使用 tenacity 函式庫: 這是一個流行的 Python 函式庫,用於添加重試邏輯。

    import openai
    import time
    from tenacity import (
        retry,
        wait_random_exponential,
        stop_after_attempt,
        retry_if_exception_type,
    )
    
    @retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6), retry=retry_if_exception_type(openai.APIRateLimitError))
    def completion_with_backoff(**kwargs):
        return openai.ChatCompletion.create(**kwargs)
    
    try:
        response = completion_with_backoff(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "user", "content": "Hello, world!"}
            ]
        )
        print(response.choices[0].message.content)
    except openai.APIRateLimitError:
        print("Failed after multiple retries due to rate limit.")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    

    這個裝飾器將在發生 APIRateLimitError 時自動重試 completion_with_backoff 函式,等待 1 到 60 秒之間的隨機指數時間,最多重試 6 次。

3.2 實施排隊系統(進階)

對於高吞吐量應用程式,簡單的退避可能不夠。

  • 訊息佇列: 使用 RabbitMQ、Kafka 或 AWS SQS 等系統來排隊 API 請求。然後,專用的工作進程可以以受控速率從佇列中消耗,遵守 OpenAI 的限制。
  • 速率限制器函式庫/中介軟體: 在您的應用程式中實施全域速率限制器,該限制器會追蹤 Token/請求的使用情況,並在接近限制時暫停請求。像 ratelimit(Python)這樣的函式庫可以提供幫助。

步驟 4:選擇正確的模型和最大 Token 數

不同的 OpenAI 模型具有不同的 Token 限制和成本。選擇合適的模型至關重要。

4.1 選擇最小可行的模型

  • gpt-3.5-turbo vs. gpt-4 gpt-4 功能更強大,但昂貴得多,且速率限制較低。對於許多任務(例如,簡單的摘要、分類),gpt-3.5-turbo 完全足夠且更具成本效益。
  • 專用模型: 如果您的任務有可用的專用模型(例如,用於向量搜尋的嵌入模型),請使用它們而不是通用聊天模型。

4.2 設定 max_tokens 參數

始終在您的 API 呼叫中設定 max_tokens 參數,特別是對於聊天完成。這限制了模型回應的長度,防止它產生過長(且昂貴)的輸出。

18+ NSFW

脫去她的衣服

脫去她的衣服

🔥 AI脫衣工具 🔥

深度裸照

深度裸照

去除衣物 • 生成裸照