Courses
Việc quản lý nhiều API của các nhà cung cấp AI nhanh chóng trở nên áp lực. Mỗi nhà cung cấp lại có phương thức xác thực, mô hình định giá và đặc tả API khác nhau. Các nhà phát triển lãng phí vô số giờ chuyển qua lại giữa OpenAI, Anthropic, Google và các nền tảng khác chỉ để truy cập các mô hình khác nhau.
OpenRouter giải quyết sự phức tạp này bằng cách cung cấp một API thống nhất kết nối bạn với hơn 400 mô hình từ hàng chục nhà cung cấp. Bạn có thể truy cập GPT-5, Claude 4, Gemini 2.5 Pro và hàng trăm mô hình khác chỉ với một khóa API và giao diện nhất quán. Nền tảng xử lý tự động chuyển đổi dự phòng, quản lý chi phí và định tuyến nhà cung cấp ở hậu trường.
Trong hướng dẫn này, tôi giải thích mọi thứ bạn cần biết về OpenRouter, từ thiết lập cuộc gọi API đầu tiên đến triển khai các tính năng nâng cao như structured outputs. Cuối bài, bạn sẽ biết cách xây dựng các ứng dụng đáng tin cậy mà không bị ràng buộc vào một nhà cung cấp duy nhất.
OpenRouter là gì?
OpenRouter là một nền tảng API thống nhất cho phép bạn truy cập hơn 400 mô hình AI từ hàng chục nhà cung cấp thông qua một endpoint duy nhất. Thay vì xoay sở với các khóa API riêng cho OpenAI, Anthropic, Google, Meta và các bên khác, bạn dùng một khóa để tiếp cận toàn bộ danh mục mô hình của họ.
Nền tảng hoạt động như một bộ định tuyến thông minh, gửi yêu cầu của bạn đến đúng nhà cung cấp đồng thời lo phần xác thực, thanh toán và xử lý lỗi. Cách tiếp cận này khắc phục nhiều rắc rối khi sử dụng nhiều nhà cung cấp AI.
Những vấn đề OpenRouter giải quyết
Làm việc với nhiều nhà cung cấp AI trở nên lộn xộn rất nhanh. Mỗi bên có định dạng API, quy trình đăng nhập và hệ thống thanh toán riêng. Bạn phải duy trì mã cho từng dịch vụ, làm chậm phát triển và khiến việc thử nghiệm mô hình mới trở nên phiền toái.
Mọi thứ còn tệ hơn khi nhà cung cấp ngừng hoạt động hoặc giới hạn tốc độ. Ứng dụng của bạn hỏng và bạn chỉ còn cách chờ đợi. Thêm nữa, việc tìm ra nhà cung cấp có giá tốt nhất cho các mô hình tương tự đòi hỏi theo dõi chi phí thủ công trên nhiều nền tảng.
Vấn đề lớn nhất là bị khóa với một nhà cung cấp. Khi bạn xây dựng mọi thứ xoay quanh API cụ thể của họ, việc chuyển sang mô hình tốt hơn hoặc rẻ hơn sau này trở thành một dự án lớn.
Cách OpenRouter khắc phục
OpenRouter giải quyết các vấn đề này bằng một bộ tính năng liên kết với nhau:
- Một khóa API dùng với 400+ mô hình từ mọi nhà cung cấp lớn
- Tự động chuyển sang nhà cung cấp dự phòng khi lựa chọn đầu tiên thất bại
- So sánh giá song song cho mọi mô hình để bạn cân đối chi phí ngay lập tức
- Tương thích với mã OpenAI hiện có — chỉ cần đổi URL endpoint
- Giám sát thời gian thực để định tuyến yêu cầu đến nhà cung cấp nhanh nhất hiện có
Những mảnh ghép này phối hợp để việc phát triển AI trơn tru và đáng tin cậy hơn.
Ai nên dùng OpenRouter?
Nhiều nhóm người dùng khác nhau hưởng lợi từ cách tiếp cận thống nhất này:
- Nhà phát triển có thể thử mô hình mới mà không cần lập tài khoản khắp nơi, tăng tốc thử nghiệm
- Nhóm doanh nghiệp đạt được thời gian hoạt động cần thiết nhờ tự động dự phòng khi nhà cung cấp gặp sự cố
- Người dùng quan tâm chi phí có thể tìm lựa chọn rẻ nhất cho nhu cầu mà không cần tính toán bảng tính
- Nhà nghiên cứu có quyền truy cập tức thì vào các mô hình tối tân mà không tốn công lập tài khoản
Giờ bạn đã hiểu OpenRouter mang lại gì, hãy bắt đầu thiết lập cuộc gọi API đầu tiên.
Yêu cầu tiên quyết
Trước khi đi sâu vào OpenRouter, bạn cần chuẩn bị vài thứ trên máy. Hướng dẫn này giả định bạn quen với lập trình Python cơ bản và đã từng làm việc với API. Bạn không cần là chuyên gia, nhưng nên hiểu các khái niệm như gửi yêu cầu HTTP và xử lý phản hồi JSON.
Bạn cần cài đặt Python 3.7 trở lên. Chúng ta sẽ dùng gói Python openai để tương tác với API của OpenRouter, cùng với python-dotenv để quản lý biến môi trường an toàn. Bạn có thể cài cả hai bằng:
pip install requests openai python-dotenv
Bạn cũng cần một tài khoản và khóa API OpenRouter. Truy cập openrouter.ai để tạo tài khoản miễn phí — bạn sẽ nhận được một khoản tín dụng nhỏ để thử nghiệm. Sau khi đăng nhập, vào mục API Keys trong cài đặt tài khoản và tạo khóa mới.
Sau khi có khóa API, hãy tạo một tệp .env trong thư mục dự án và thêm khóa của bạn như sau:
OPENROUTER_API_KEY=your_api_key_here
Cách này giúp giữ khóa API an toàn và tách khỏi mã nguồn. Nếu bạn định dùng OpenRouter vượt quá mức thử nghiệm, bạn sẽ cần nạp tín dụng thông qua trang Credits.
Với những nền tảng này, bạn đã sẵn sàng thực hiện cuộc gọi API đầu tiên qua OpenRouter.
Thực hiện cuộc gọi API đầu tiên trong OpenRouter
Bắt đầu với OpenRouter cực kỳ đơn giản nếu bạn từng dùng OpenAI SDK. Bạn chỉ cần đổi một dòng mã là có ngay quyền truy cập hàng trăm mô hình từ các nhà cung cấp khác nhau.
Yêu cầu đầu tiên và thiết lập
Hãy bắt đầu ngay với một ví dụ hoạt động minh họa cách tiếp cận của OpenRouter:
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY"),
)
response = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=[
{
"role": "user",
"content": "Write a haiku about debugging code at 2 AM"
}
]
)
print(response.choices[0].message.content)
Night hum, coffee cooled
cursor blinks, bug hides somewhere
I chase ghosts 'til dawn
Điều kỳ diệu xảy ra ở hai chỗ. Thứ nhất, tham số base_url chuyển hướng yêu cầu của bạn đến máy chủ của OpenRouter thay vì OpenAI. Thứ hai, tên mô hình theo định dạng provider/model-name — openai/gpt-5-mini thay vì chỉ gpt-5-mini. Điều này cho OpenRouter biết bạn muốn phiên bản của nhà cung cấp nào trong khi vẫn giữ giao diện quen thuộc. Dưới đây là một số mô hình phổ biến bạn có thể cắm vào ví dụ trên mà không gặp lỗi:
- google/gemini-2.0-flash-001
- google/gemini-2.5-pro
- mistralai/mistral-nemo
- deepseek/deepseek-r1-distill-qwen-32b
Giờ khi bạn thấy làm việc với các mô hình khác nhau dễ thế nào, có thể bạn sẽ thắc mắc: chuyện gì xảy ra khi mô hình bạn chọn không khả dụng? Làm sao xây dựng ứng dụng vẫn ổn định ngay cả khi nhà cung cấp gặp sự cố? Đó là lúc các tính năng định tuyến và khả năng phục hồi của OpenRouter phát huy tác dụng.
Định tuyến mô hình để tăng khả năng chịu lỗi
Xây dựng ứng dụng AI đáng tin cậy nghĩa là phải chuẩn bị cho những điều bất ngờ. Nhà cung cấp có thể downtime, mô hình chạm giới hạn tốc độ, và đôi khi kiểm duyệt nội dung chặn yêu cầu của bạn. Định tuyến mô hình là giải pháp của OpenRouter — tự động chuyển giữa các mô hình khác nhau để giữ ứng dụng chạy mượt.
Thiết lập phương án dự phòng thủ công
Cách đơn giản nhất để tăng khả năng chịu lỗi là chỉ định các mô hình dự phòng. Khi lựa chọn chính thất bại, OpenRouter thử các phương án thay thế theo thứ tự. Tham số extra_body truyền các hướng dẫn định tuyến này đến API của OpenRouter vì OpenAI SDK không hỗ trợ tính năng này một cách tự nhiên:
response = client.chat.completions.create(
model="moonshotai/kimi-k2", # Primary choice
messages=[
{"role": "user", "content": "Explain quantum computing in simple terms"}
],
extra_body={
"models": ["anthropic/claude-sonnet-4", "deepseek/deepseek-r1"]
}
)
print(f"Response from: {response.model}")
print(response.choices[0].message.content)
Response from: moonshotai/kimi-k2
Imagine a normal computer bit as a tiny light-switch that can only be OFF (0) or ON (1)...
OpenRouter thử Kimi-K2 trước. Nếu không khả dụng, bị giới hạn tốc độ hoặc bị chặn, nó sẽ tự động thử Claude Sonnet 4, rồi đến DeepSeek R1. Trường response.model cho biết mô hình nào thực sự đã phản hồi.
Auto router để tiện lợi tối đa
Khi đã hiểu dự phòng thủ công, auto router trở nên rất hấp dẫn. Nó xử lý lựa chọn mô hình và dự phòng tự động, được hỗ trợ bởi hệ thống đánh giá của NotDiamond:
response = client.chat.completions.create(
model="openrouter/auto",
messages=[
{"role": "user", "content": "Debug this Python code in 3 sentences: def factorial(n): return n * factorial(n-1)"}
]
)
print(f"Auto router selected: {response.model}")
print(response.choices[0].message.content)
Auto router selected: openai/chatgpt-4o-latest
The given code is missing a base case, which causes infinite recursion and eventually a RecursionError. To fix it, add a base case like `if n == 0: return 1` before the recursive call. Here's the corrected version:
\```python
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)
\```
Auto router phân tích prompt của bạn và chọn mô hình tốt nhất hiện có, với dự phòng tích hợp nếu lựa chọn đầu tiên không khả dụng. Bạn có được khả năng chịu lỗi mà không cần cấu hình gì. Tuy nhiên, hãy dùng auto-router thận trọng trong các tình huống nhạy cảm hoặc nổi bật vì nó có xu hướng đánh giá thấp độ phức tạp của vấn đề và do đó chọn mô hình dung lượng thấp hơn.
Xây dựng chiến lược dự phòng hiệu quả
Không phải mô hình nào cũng là dự phòng tốt cho nhau. Thời gian ngừng hoạt động của nhà cung cấp có thể ảnh hưởng đến tất cả mô hình của công ty đó, vì vậy hãy chọn dự phòng từ các nhà cung cấp khác nhau. Giới hạn tốc độ và chi phí khác nhau đáng kể, nên ghép các mô hình đắt tiền với lựa chọn rẻ hơn:
# Good fallback chain: different providers, decreasing cost
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[
{"role": "user", "content": "Your prompt here"}
],
extra_body={
"models": [
"x-ai/grok-4", # Close performance
"moonshotai/kimi-k2", # Cheaper
"deepseek/deepseek-r1:free" # Free backup
]
}
)
Chuỗi này cho bạn chất lượng cao cấp khi khả dụng, hiệu năng vững vàng làm dự phòng và khả dụng đảm bảo như biện pháp cuối cùng. Chính sách kiểm duyệt nội dung cũng khác nhau giữa các nhà cung cấp, nên đa dạng hóa chuỗi sẽ bao phủ tốt hơn cho các chủ đề nhạy cảm.
Tìm mô hình cho chuỗi dự phòng
Trang mô hình cho phép bạn lọc theo nhà cung cấp và năng lực để xây dựng chuỗi. Nhiều mô hình mạnh như DeepSeek R1 và Kimi-K2 miễn phí vì là mã nguồn mở, rất phù hợp làm dự phòng. Các mô hình miễn phí có giới hạn 50 yêu cầu mỗi ngày cho người dùng mới, hoặc 1000 yêu cầu mỗi ngày nếu bạn đã mua 10 tín dụng.
Với các ứng dụng động, bạn có thể khám phá mô hình bằng lập trình:
def get_provider_models(api_key: str, provider: str) -> list[str]:
r = requests.get(
"https://openrouter.ai/api/v1/models",
headers={"Authorization": f"Bearer {api_key}"}
)
return [m["id"] for m in r.json()["data"] if m["id"].startswith(provider)]
# Build fallbacks across providers
openai_models = get_provider_models(api_key, "openai/")
anthropic_models = get_provider_models(api_key, "anthropic/")
Cách làm này cho phép bạn xây dựng các chuỗi dự phòng vững chắc và thích ứng khi các mô hình mới xuất hiện.
Streaming cho phản hồi thời gian thực
Khi làm việc với các mô hình AI, đặc biệt cho phản hồi dài, người dùng mong muốn thấy kết quả hiện dần thay vì chờ toàn bộ. Streaming giải quyết điều này bằng cách gửi các đoạn phản hồi khi chúng được tạo ra, tạo trải nghiệm tương tác hơn giống giao diện của ChatGPT.
Thiết lập streaming cơ bản
Để thiết lập streaming trong OpenRouter, thêm stream=True vào yêu cầu. Phản hồi trở thành một iterator trả về các đoạn khi mô hình tạo ra chúng:
response = client.chat.completions.create(
model="openai/gpt-5",
messages=[
{"role": "user", "content": "Write a detailed explanation of how neural networks learn"}
],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")
Mỗi đoạn chứa một phần nhỏ của phản hồi. Trường delta.content giữ mảnh văn bản mới, và chúng ta in ngay không xuống dòng để tạo hiệu ứng streaming. Tham số end="" ngăn print thêm dòng mới giữa các đoạn.
Xây dựng trình xử lý streaming tốt hơn
Đối với ứng dụng production, bạn sẽ muốn kiểm soát nhiều hơn quá trình streaming. Đây là một trình xử lý toàn diện hơn để quản lý toàn bộ phản hồi:
def stream_response(model, messages, show_progress=True):
response = client.chat.completions.create(
model=model,
messages=messages,
stream=True
)
complete_response = ""
for chunk in response:
if chunk.choices[0].delta.content is not None:
content = chunk.choices[0].delta.content
complete_response += content
if show_progress:
print(content, end="", flush=True)
if show_progress:
print() # Add final newline
return complete_response
# Use it with different models
result = stream_response(
"anthropic/claude-sonnet-4",
[{"role": "user", "content": "Explain quantum entanglement like I'm 12 years old"}]
)
Trình xử lý này vừa lưu toàn bộ phản hồi vừa hiển thị tiến độ, mang lại cả trải nghiệm streaming lẫn văn bản cuối cùng, đồng thời định dạng đầu ra phù hợp.
Streaming biến trải nghiệm người dùng từ “chờ đợi và hy vọng” thành “theo dõi tiến độ đang diễn ra”. Điều này giúp ứng dụng AI của bạn phản hồi nhanh nhạy và cuốn hút hơn.
Xử lý Reasoning Tokens trong OpenRouter
Một số mô hình AI có thể hiển thị quá trình “suy nghĩ” trước khi đưa ra câu trả lời cuối cùng. Các reasoning tokens này cung cấp cái nhìn minh bạch về cách mô hình tiếp cận vấn đề phức tạp, cho thấy lập luận từng bước dẫn đến kết luận. Hiểu được suy luận nội bộ giúp bạn kiểm chứng câu trả lời, gỡ lỗi hành vi mô hình và xây dựng ứng dụng đáng tin cậy hơn.
Reasoning tokens là gì
Reasoning tokens xuất hiện trong một trường reasoning riêng biệt trong phản hồi, tách khỏi nội dung chính. Các mô hình hỗ trợ reasoning theo nhiều cách khác nhau — một số dùng mức độ nỗ lực, số khác dùng hạn ngạch token.
Đây là một ví dụ đơn giản cho thấy reasoning hoạt động thế nào:
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[
{"role": "user", "content": "How many 'r's are in the word 'strrawberry'?"}
],
max_tokens=2048,
extra_body={
"reasoning": {
"max_tokens": 512
}
}
)
print("Final answer:")
print(response.choices[0].message.content)
print("\nReasoning process:")
print(response.choices[0].message.reasoning)
Final answer:
To count the 'r's in 'strrawberry', I'll go through each letter:
...
There are **4** 'r's in the word 'strrawberry'.
Reasoning process:
...
Mô hình sẽ hiển thị cả câu trả lời cuối lẫn suy luận nội bộ dẫn đến kết luận đó. Đầu ra kép này giúp bạn hiểu mô hình tiếp cận vấn đề có hợp lý không.
Điều chỉnh cường độ reasoning
Bạn có thể kiểm soát mức độ nỗ lực suy luận của mô hình bằng hai cách. Tham số effort hoạt động với các mô hình như dòng o-series của OpenAI và dùng các mức tương ứng với tỷ lệ phần trăm token cụ thể dựa trên thiết lập max_tokens:
- Nỗ lực cao: Dùng khoảng 80%
max_tokenscho reasoning - Nỗ lực trung bình: Dùng khoảng 50%
max_tokenscho reasoning - Nỗ lực thấp: Dùng khoảng 20%
max_tokenscho reasoning
# High effort reasoning for complex problems
response = client.chat.completions.create(
model="deepseek/deepseek-r1",
messages=[
{"role": "user", "content": "Solve this step by step: If a train travels 240 miles in 3 hours, then speeds up by 20 mph for the next 2 hours, how far does it travel total?"}
],
max_tokens=4000, # High effort will use ~3200 tokens for reasoning
extra_body={
"reasoning": {
"effort": "high"
}
}
)
print("Problem solution:")
print(response.choices[0].message.content)
print("\nStep-by-step reasoning:")
print(response.choices[0].message.reasoning)
Với các mô hình hỗ trợ phân bổ token trực tiếp, như các mô hình của Anthropic, bạn có thể chỉ định ngân sách reasoning cụ thể:
def get_reasoning_response(question, reasoning_budget=2000):
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[{"role": "user", "content": question}],
max_tokens=10000,
extra_body={
"reasoning": {
"max_tokens": reasoning_budget # Exact token allocation
}
}
)
return response
# Compare different reasoning budgets
response = get_reasoning_response(
"What's bigger: 9.9 or 9.11? Explain your reasoning carefully.",
reasoning_budget=3000
)
print("Answer:", response.choices[0].message.content)
print("Detailed reasoning:", response.choices[0].message.reasoning)
Ngân sách token cao thường tạo ra lập luận kỹ lưỡng hơn, trong khi ngân sách thấp cho quá trình suy nghĩ nhanh hơn nhưng ít chi tiết.
Bảo toàn reasoning trong hội thoại
Khi xây dựng hội thoại nhiều lượt, bạn cần giữ cả reasoning và câu trả lời cuối để duy trì ngữ cảnh. Điều này đặc biệt quan trọng với thảo luận phức tạp, nơi quá trình suy nghĩ của mô hình ảnh hưởng đến các phản hồi sau đó:
# First message with reasoning
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[
{"role": "user", "content": "Should I invest in renewable energy stocks? Consider both risks and opportunities."}
],
extra_body={
"reasoning": {
"max_tokens": 3000
}
}
)
# Build conversation history with reasoning preserved
messages = [
{"role": "user", "content": "Should I invest in renewable energy stocks? Consider both risks and opportunities."},
{
"role": "assistant",
"content": response.choices[0].message.content,
"reasoning_details": response.choices[0].message.reasoning_details # Preserve reasoning
},
{"role": "user", "content": "What about solar energy specifically? How does that change your analysis?"}
]
# Continue conversation with reasoning context
follow_up = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=messages,
extra_body={
"reasoning": {
"max_tokens": 2000
}
}
)
print("Follow-up answer:")
print(follow_up.choices[0].message.content)
print("\nContinued reasoning:")
print(follow_up.choices[0].message.reasoning)
Trường reasoning_details giữ nguyên chuỗi suy luận đầy đủ, cho phép mô hình phát triển dựa trên phân tích trước đó khi trả lời câu hỏi tiếp theo. Điều này tạo ra hội thoại mạch lạc và nhận thức ngữ cảnh tốt hơn.
Cân nhắc về chi phí và thanh toán
Reasoning tokens được tính phí như token đầu ra, nên sẽ làm tăng chi phí sử dụng. Tuy nhiên, chúng thường cải thiện chất lượng phản hồi đủ để xứng đáng, nhất là với tác vụ phức tạp nơi độ chính xác quan trọng hơn tốc độ. Theo tài liệu của OpenRouter, reasoning tokens có thể cải thiện hiệu năng mô hình trên các bài toán khó đồng thời mang lại tính minh bạch cho quá trình ra quyết định.
Với ứng dụng nhạy chi phí, bạn có thể cân bằng chất lượng reasoning so với chi phí bằng cách điều chỉnh mức effort hoặc ngân sách token dựa trên độ phức tạp của tác vụ. Câu hỏi đơn giản có thể không cần reasoning, trong khi vấn đề phức tạp hưởng lợi từ reasoning mức cao.
Làm việc với mô hình đa phương thức trong OpenRouter
Từ nãy bạn làm việc với văn bản, nhưng khi cần phân tích hình ảnh hoặc tài liệu thì sao? Có thể bạn muốn đặt câu hỏi về một biểu đồ, trích xuất thông tin từ PDF, hoặc mô tả những gì đang xảy ra trong ảnh. Đó là lúc các mô hình đa phương thức phát huy — chúng có thể hiểu cả văn bản và nội dung trực quan trong cùng một yêu cầu.
Hiểu năng lực đa phương thức
Thay vì cố mô tả hình ảnh bằng chữ, bạn có thể gửi trực tiếp hình ảnh và đặt câu hỏi về nó. Điều này khiến ứng dụng của bạn trực quan hơn nhiều vì mô hình thấy đúng thứ bạn đang làm việc cùng. Bạn không phải đoán xem mô tả bằng chữ có nêu đủ chi tiết quan trọng hay không.
Bạn dùng các mô hình đa phương thức thông qua cùng giao diện, chỉ thêm tham số attachments để đính kèm nội dung trực quan. Tệp đính kèm hoạt động với mọi mô hình trên OpenRouter. Ngay cả khi một mô hình không hỗ trợ PDF hoặc hình ảnh một cách tự nhiên, OpenRouter sẽ phân tích các tệp này nội bộ và truyền nội dung cho mô hình.
Làm việc với hình ảnh
Bạn có thể đưa hình ảnh vào yêu cầu qua URL hoặc mã hóa base64. Nếu ảnh đã có sẵn trực tuyến, dùng URL sẽ đơn giản hơn:
response = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=[
{
"role": "user",
"content": "What's happening in this image? Describe the scene in detail."
}
],
extra_body={
"attachments": [
{
"type": "image/jpeg",
"url": "https://example.com/photo.jpg"
}
]
}
)
print(response.choices[0].message.content)
Với ảnh cục bộ, bạn có thể dùng mã hóa base64:
import base64
def encode_image_to_base64(image_path):
with open(image_path, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
return encoded_string
# Analyze a local screenshot
encoded_image = encode_image_to_base64("screenshot.png")
response = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=[
{
"role": "user",
"content": "This is a screenshot of a data dashboard. What insights can you extract from the charts and metrics shown?"
}
],
extra_body={
"attachments": [
{
"type": "image/png",
"data": encoded_image
}
]
}
)
print(response.choices[0].message.content)
Mô hình sẽ xem ảnh thực tế và đưa ra những nhận định cụ thể về những gì nó thấy, không chỉ các phản hồi chung chung.
Xử lý tài liệu PDF
Xử lý PDF cũng tương tự nhưng mở ra khả năng phân tích tài liệu. Bạn có thể đặt câu hỏi về báo cáo, phân tích biểu mẫu, hoặc trích xuất thông tin từ tài liệu phức tạp:
def encode_pdf_to_base64(pdf_path):
with open(pdf_path, "rb") as pdf_file:
encoded_string = base64.b64encode(pdf_file.read()).decode('utf-8')
return encoded_string
# Analyze a research paper
encoded_pdf = encode_pdf_to_base64("research_paper.pdf")
response = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=[
{
"role": "user",
"content": "Summarize the key findings from this research paper. What are the main conclusions and methodology used?"
}
],
extra_body={
"attachments": [
{
"type": "application/pdf",
"data": encoded_pdf
}
]
}
)
print(response.choices[0].message.content)
Cách này rất hữu ích cho báo cáo tài chính, bài báo học thuật, hợp đồng hoặc bất kỳ PDF nào bạn cần AI phân tích nội dung thực. Bạn cũng có thể đính kèm nhiều tệp trong một yêu cầu nếu cần so sánh hình ảnh hoặc phân tích nhiều tài liệu cùng lúc.
Chi phí và lựa chọn mô hình
Yêu cầu đa phương thức tốn nhiều chi phí hơn so với chỉ văn bản vì bạn xử lý thêm các loại dữ liệu. Hình ảnh và PDF cần nhiều năng lực tính toán hơn, phản ánh vào giá. Bạn có thể xem giá đa phương thức cụ thể của từng mô hình trên trang mô hình.
Các mô hình khác nhau có thế mạnh khác nhau với nội dung trực quan. Có mô hình giỏi phân tích ảnh chi tiết, có mô hình mạnh về hiểu tài liệu. Bạn nên thử nghiệm để tìm lựa chọn phù hợp nhất với nhu cầu và ngân sách của mình.
Sử dụng Structured Outputs
Khi xây dựng ứng dụng thực tế, bạn cần định dạng dữ liệu có thể dự đoán để mã của bạn phân tích đáng tin cậy. Phản hồi văn bản tự do phù hợp cho giao diện trò chuyện, nhưng tệ cho các ứng dụng cần trích xuất thông tin cụ thể. Thay vì nhận về văn bản khó đoán mà bạn phải parse bằng regex hoặc hy vọng mô hình định dạng đúng, structured outputs buộc mô hình trả về JSON được đảm bảo với đúng trường và kiểu dữ liệu bạn cần. Điều này loại bỏ lỗi phân tích và đơn giản hóa mã ứng dụng của bạn.
Cấu trúc của yêu cầu structured output
Structured outputs dùng tham số response_format với cấu trúc cơ bản như sau:
"response_format": {
"type": "json_schema", # Always this for structured outputs
"json_schema": {
"name": "your_schema_name", # Name for your schema
"strict": True, # Enforce strict compliance
"schema": {
# Your actual JSON schema definition goes here
}
}
}
Ví dụ phân tích cảm xúc
Hãy đi qua một ví dụ hoàn chỉnh trích xuất cảm xúc từ văn bản. Ví dụ này cho thấy structured outputs hoạt động trong thực tế thế nào:
response = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=[
{"role": "user", "content": "Analyze the sentiment: 'This movie was absolutely terrible!'"}
],
extra_body={
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "sentiment_analysis",
"strict": True,
"schema": {
"type": "object",
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
"confidence": {"type": "number"}
},
"required": ["sentiment", "confidence"]
}
}
}
}
)
import json
result = json.loads(response.choices[0].message.content)
print(result)
{'sentiment': 'negative', 'confidence': 0.98}
Cấu trúc này hoạt động như sau:
sentiment: Trường kiểu chuỗi bị giới hạn bởienumvới ba giá trị cụ thể. Mô hình không thể trả về ngoài "positive", "negative" hoặc "neutral"confidence: Trường số cho điểm tự tin của mô hìnhrequired: Cả hai trường phải có trong phản hồi — mô hình không thể bỏ quastrict: True: Buộc tuân thủ nghiêm ngặt cấu trúc schema
Không có structured outputs, bạn có thể nhận các phản hồi kiểu “Cảm xúc rất tiêu cực với độ tự tin cao” hoặc “Negative (chắc 95%)”. Với schema, bạn luôn nhận JSON có thể phân tích ngay trong mã.
Thiết lập strict: True buộc mô hình tuân thủ nghiêm — không thể lệch khỏi cấu trúc của bạn. Mảng required chỉ rõ các trường bắt buộc. Bạn có thể dùng enum để giới hạn giá trị, array cho danh sách và object lồng nhau cho dữ liệu phức tạp.
Tương thích mô hình
Không phải tất cả mô hình đều hỗ trợ structured outputs, nhưng hầu hết mô hình hiện đại có. Bạn có thể kiểm tra trên trang mô hình để biết tương thích. Khi một mô hình không hỗ trợ structured outputs một cách tự nhiên, OpenRouter thường xử lý định dạng ở phía nội bộ.
Structured outputs biến phản hồi AI từ văn bản khó đoán thành dữ liệu đáng tin cậy mà ứng dụng của bạn có thể phụ thuộc. Với mọi trường hợp production cần trích xuất dữ liệu nhất quán, tính năng này là thiết yếu.
Kết luận
Chúng ta đã học cách truy cập hàng trăm mô hình AI thông qua API thống nhất của OpenRouter, từ yêu cầu đầu tiên đến triển khai các tính năng như streaming, reasoning tokens và structured outputs.
Khả năng dự phòng tự động và định tuyến mô hình của nền tảng giúp ứng dụng của bạn vẫn đáng tin cậy ngay cả khi từng nhà cung cấp gặp sự cố. Với cùng mẫu mã, chúng ta có thể so sánh mô hình, đổi nhà cung cấp và tìm lựa chọn phù hợp nhất cho từng tác vụ mà không cần quản lý nhiều khóa API.
Hãy bắt đầu thử nghiệm với các yêu cầu đơn giản và dần dần dùng thêm tính năng khi nhu cầu tăng. Thử các mô hình khác nhau cho từng loại tác vụ — một số phù hợp viết sáng tạo, số khác mạnh về phân tích dữ liệu hoặc bài toán suy luận.
Những kiến thức bạn có được ở đây giúp bạn xây dựng ứng dụng AI không bị khóa với bất kỳ nhà cung cấp nào, mang lại sự tự do để thích ứng khi các mô hình và tính năng mới xuất hiện.
Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt nhàm chán. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, và đang ấp ủ thêm một khóa nữa. Nội dung của tôi đã tiếp cận hơn 5 triệu lượt xem, trong đó có 20 nghìn người trở thành người theo dõi trên cả Medium và LinkedIn.
