در چشمانداز بهسرعت در حال تحول هوش مصنوعی مولد، رویکرد «جعبه سیاه» برای استنتاج مدلهای زبانی بزرگ (LLM) منسوخ میشود. کاربران امروزی بازخورد فوری، تعامل و حس حضور را در مکالمات خود با هوش مصنوعی انتظار دارند. این انتظار، جریان توکن را به یک مؤلفه حیاتی برای زیرساختهای هوش مصنوعی با عملکرد بالا تبدیل کرده است. برای توسعهدهندگان متوسط و پیشرفته، درک مکانیکهای جریان توکن دیگر یک انتخاب نیست—بلکه اساسی برای ساخت برنامههای هوش مصنوعی رقابتی و کاربرپسند است.
چرا جریان؟ چالش تأخیر
فراخوانیهای API سنتی بر اساس مدل درخواست-پاسخ عمل میکنند که در آن کلاینت یک پرامپت ارسال میکند، منتظر تکمیل کامل میماند و کل پیکربندی متن را دریافت میکند. در زمینه یک LLM که یک مقاله ۵۰۰ کلمهای تولید میکند، این فرآیند میتواند چندین ثانیه طول بکشد. رابط کاربری در این مدت ثابت میماند که منجر به تجربه کاربری ضعیف ناشی از تأخیر «زمان تا اولین بایت» (TTFB) میشود.
جریان توکن، بهویژه رویدادهای ارسالی سرور (SSE)، به سرور اجازه میدهد تا پاسخها را به صورت تدریجی ارسال کند. به محض اینکه LLM اولین توکن را تولید میکند، آن را به کلاینت ارسال میکند. این کار افکت بصری نوشتن متن را به صورت زمان واقعی ایجاد میکند و عملکرد ادراکشده و مشارکت کاربر را به شدت بهبود میبخشد. برای مهندسان زیرساخت، این امر پارادایم را از انتقال دادههای دستهای به جریان دادهای پیوسته و با تأخیر کم تغییر میدهد.
پیادهسازی جریان توکن با پایتون
پیادهسازی جریان نیازمند سروری است که بتواند قطعات داده را تولید کند (yield) به جای ارسال یک پاسخ کامل واحد. در پایتون، با استفاده از چارچوبهایی مانند FastAPI یا Starlette، این کار با استفاده از ژنراتورهای ناهمزمان (asynchronous) انجام میشود. در زیر یک مثال عملی از نحوه پیادهسازی یک نقطه پایانی (endpoint) جریان آورده شده است.
ابتدا، مطمئن شوید که کتابخانههای لازم نصب شدهاند:
pip install fastapi uvicorn openai
در اینجا یک پیادهسازی قوی برای یک نقطه پایانی جریان آورده شده است:
import asyncio
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
app = FastAPI()
client = AsyncOpenAI()
async def generate_tokens(prompt: str):
"""ژنراتور ناهمزمان برای تولید توکنها یکی یکی."""
stream = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
stream=True
)
async for chunk in stream:
# استخراج توکن از قطعه
token = chunk.choices[0].delta.content
if token:
yield f"data: {token}\n\n"
@app.get("/stream")
async def stream_response(user_input: str):
return StreamingResponse(
generate_tokens(user_input),
media_type="text/event-stream"
)
در این کد، تابع generate_tokens به عنوان یک ژنراتور ناهمزمان عمل میکند. این تابع از طریق جریان OpenAI تکرار میکند، توکنهای فردی را استخراج میکند و آنها را به صورت پیکربندیهای SSE ارسال میکند. StreamingResponse در FastAPI اتصال HTTP را مدیریت کرده، آن را باز نگه میدارد و این قطعات را به محض در دسترس بودن به کلاینت ارسال میکند.
مدیریت سمت کلاینت: خواندن جریان
در سمت کلاینت، مدیریت SSE نیازمند تجزیه (parse) جریان دادههای ورودی است. در جاوااسکریپت، API Fetch راه تمیزی برای مدیریت این موضوع فراهم میکند. بدنه پاسخ حاوی یک ReadableStream است که میتوان آن را به صورت ناهمزمان پردازش کرد.
async function handleStream(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
// تجزیه فرمت SSE و افزودن به رابط کاربری
const tokens = chunk.split('\n').filter(line => line.startsWith('data: '));
for (const line of tokens) {
console.log(line.replace('data: ', ''));
}
}
}
نتیجهگیری
جریان توکن فراتر از یک پرداخت ظاهری UX است؛ این یک الگوی معماری بنیادی برای برنامههای هوش مصنوعی مدرن است. با جداسازی زمان تولید از تعامل کاربر، سیستمهایی ایجاد میکنیم که پاسخگو و هوشمند به نظر میرسند. چه یک چتبات، چه یک ابزار تکمیل کد، و چه یک داشبورد تحلیل دادههای زمان واقعی میسازید، تسلط بر تعامل بین ژنراتورهای ناهمزمان سمت سرور و خوانندههای جریان سمت کلاینت برای ارائه نسل بعدی تجربیات هوش مصنوعی ضروری است.