Vấn đềBạn đang chuyển sang sử dụng Python bất đồng bộ (asynchronous) để tăng tốc các lệnh gọi OpenAI API. Tuy nhiên, thay vì kết quả nhanh hơn, bạn lại gặp một loạt thông báo lỗi màu đỏ. Điều này thường xảy ra ngay khi bạn chuyển từ client OpenAI() tiêu chuẩn sang AsyncOpenAI() và cố gắng thực thi mã bằng asyncio.run().
Notebook của bạn có khả năng sẽ kích hoạt lỗi cụ thể này:
RuntimeError: This event loop is already running. Passing coroutines is forbidden when an event loop is already running.
Tại sao lỗi này xảy ra trong JupyterĐiều này xảy ra vì Jupyter Notebook chạy trên một kernel IPython. Kernel này vốn đã bận chạy một vòng lặp sự kiện (event loop) asyncio để giữ cho giao diện luôn phản hồi. Vì thư viện tiêu chuẩn của Python không cho phép các vòng lặp lồng nhau, việc gọi asyncio.run() bên trong một notebook sẽ gây ra xung đột trực tiếp. Nó cố gắng bắt đầu một vòng lặp mới trong khi một vòng lặp khác đang hoạt động.
Client AsyncOpenAI của OpenAI phụ thuộc vào các vòng lặp này để thực hiện các yêu cầu không chặn (non-blocking). Khi phát hiện hai vòng lặp đang tranh giành quyền kiểm soát, nó sẽ tự đóng để ngăn chặn hư hỏng dữ liệu.
Cách khắc phục nhanh: nest-asyncioGói nest-asyncio là một tiện ích nhỏ giúp cấu hình lại vòng lặp hiện có. Nó cho phép bạn chạy asyncio.run() ngay cả khi một vòng lặp đã hoạt động. Đây là lựa chọn tốt nhất nếu bạn muốn giữ mã của mình tương thích với các script Python tiêu chuẩn.
Bước 1: Cài đặt thư việnChạy lệnh này trong một ô (cell) của notebook để cài đặt thư viện dung lượng 1MB này:
%pip install nest-asyncio
Bước 2: Áp dụng bản váThêm hai dòng này vào đầu notebook của bạn. Việc này chỉ cần thực hiện một lần cho mỗi phiên làm việc.
import nest_asyncio
nest_asyncio.apply()
Bước 3: Chạy mã AsyncOpenAI của bạnGiờ đây, các hàm async của bạn sẽ chạy mà không bị lỗi. Dưới đây là một ví dụ hoàn chỉnh:
import asyncio
from openai import AsyncOpenAI
import nest_asyncio
nest_asyncio.apply()
client = AsyncOpenAI(api_key="thay_api_key_cua_ban_tai_day")
async def fetch_completion():
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Xin chào!"}]
)
print(response.choices[0].message.content)
asyncio.run(fetch_completion())
Cách khắc phục hiện đại: Top-Level AwaitNếu bạn muốn mã nguồn gọn sạch hơn, hãy bỏ qua thư viện bổ sung. Các môi trường Jupyter hiện đại (IPython 7.0 trở lên) hỗ trợ "top-level await" ngay lập tức. Điều này có nghĩa là bạn có thể await các hàm trực tiếp trong một cell mà không cần sử dụng asyncio.run().
Cách tiếp cận này giúp giảm bớt các đoạn mã rườm rà (boilerplate) và thường được coi là phương pháp tốt nhất cho các môi trường tương tác. Dưới đây là phiên bản tinh gọn:
from openai import AsyncOpenAI
client = AsyncOpenAI(api_key="thay_api_key_cua_ban_tai_day")
# Không cần asyncio.run() ở đây
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Kể cho tôi một câu chuyện đùa."}]
)
print(response.choices[0].message.content)
Để xác minh cách khắc phụcKiểm tra cách khắc phục bằng cách chạy ba yêu cầu cùng lúc. Điều này chứng minh môi trường của bạn xử lý đồng thời (concurrency) chính xác. Nếu mã bên dưới in ra ba phản hồi cùng lúc, thiết lập của bạn đã hoàn hảo:
async def test_concurrent():
tasks = [
client.chat.completions.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": f"Đếm đến {i}"}])
for i in range(1, 4)
]
responses = await asyncio.gather(*tasks)
for res in responses:
print(res.choices[0].message.content)
await test_concurrent()

