تدفق المخرجات في وكلاء CLI
طباعة الرموز المتدفقة حرفًا حرفًا في واجهات الطرفية
تدفق المخرجات في وكلاء CLI درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.
أهمية البث لوكلاء CLI
من دون البث، لا يطبع وكيل CLI شيئًا حتى تصبح استجابة LLM الكاملة جاهزة، وقد يستغرق ذلك من 5 إلى 30 ثانية. ويحدّق المستخدمون في طرفية فارغة متسائلين عما إذا كان البرنامج قد تعطل.
أما مع البث، فتظهر الرموز أثناء توليدها، ما يوفر استجابة فورية وتجربة أفضل بكثير.
تفعيل البث في OpenAI SDK
مرّروا stream=True إلى chat.completions.create(). يعيد الاستدعاء مولّدًا بدلًا من كائن استجابة كامل. تكرّروا عليه لمعالجة الأجزاء عند وصولها.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': 'Explain Python generators in 3 sentences.'}],
stream=True # <-- enable streaming
)
# Each chunk arrives as it is generated
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end='', flush=True)
print() # newline after the response is completeprint() مقابل sys.stdout.write()
عند استخدام البث، استخدموا print(text, end='', flush=True) أو sys.stdout.write(text) متبوعًا بـ sys.stdout.flush(). من دون flush=True، قد تخزّن Python المخرجات مؤقتًا وتطبعها دفعة واحدة، ما يلغي الغرض من البث.
import sys
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def stream_to_terminal(messages: list):
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True
)
full_response = ''
for chunk in stream:
token = chunk.choices[0].delta.content or ''
full_response += token
# Option 1: print with flush
print(token, end='', flush=True)
# Option 2: sys.stdout.write + flush
# sys.stdout.write(token)
# sys.stdout.flush()
print() # final newline
return full_responseجمع الاستجابة الكاملة أثناء البث
غالبًا ما تحتاجون إلى نص الاستجابة الكامل بعد اكتمال البث، سواء لتخزينه أو لمعالجته لاحقًا أو لعرضه. اجمعوا الرموز في سلسلة نصية أثناء طباعتها.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def stream_and_collect(messages: list) -> str:
full_text = ''
print('Agent: ', end='', flush=True)
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True
)
for chunk in stream:
token = chunk.choices[0].delta.content or ''
full_text += token
print(token, end='', flush=True)
print() # newline
return full_text
# The return value contains the complete response for storage
# response_text = stream_and_collect(history)
# history.append({'role': 'assistant', 'content': response_text})البث غير المتزامن باستخدام AsyncOpenAI
في بنى الوكلاء غير المتزامنة، استخدموا AsyncOpenAI وasync for للتكرار على أجزاء البث دون حظر حلقة الأحداث.
import asyncio
import openai
async def async_stream_agent(query: str) -> str:
client = openai.AsyncOpenAI(api_key='YOUR_API_KEY')
stream = await client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': query}],
stream=True
)
full_text = ''
print('Agent: ', end='', flush=True)
async for chunk in stream:
token = chunk.choices[0].delta.content or ''
full_text += token
print(token, end='', flush=True)
print()
return full_text
# asyncio.run(async_stream_agent('What is asyncio?'))اكتشاف نهاية البث باستخدام finish_reason
يحتوي الجزء الأخير من البث على قيمة غير فارغة في finish_reason. تحقّقوا منها لمعرفة سبب انتهاء البث: 'stop' = اكتمال عادي، 'length' = اقتطاع، 'tool_calls' = الحاجة إلى استدعاء دالة.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def stream_with_finish_detection(messages: list):
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True
)
finish_reason = None
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end='', flush=True)
if chunk.choices[0].finish_reason:
finish_reason = chunk.choices[0].finish_reason
print()
if finish_reason == 'length':
print('[WARNING: Response was truncated. Try increasing max_tokens.]')
elif finish_reason == 'stop':
pass # normal completion
return finish_reasonألوان ANSI في مخرجات الطرفية
تضيف رموز هروب ANSI ألوانًا إلى مخرجات الطرفية. استخدموها للتمييز بصريًا بين بادئة الوكيل ومطالبة إدخال المستخدم والتحذيرات. وتوفر مكتبة colorama دعمًا متعدد المنصات، بما في ذلك Windows.
# pip install colorama
from colorama import Fore, Style, init
init(autoreset=True) # reset color after each print
def print_colored_stream(messages: list, client):
# Print agent prefix in cyan
print(Fore.CYAN + 'Agent: ' + Style.RESET_ALL, end='', flush=True)
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True
)
for chunk in stream:
token = chunk.choices[0].delta.content or ''
print(token, end='', flush=True)
print()
# Also useful:
# print(Fore.GREEN + 'Success!') — green
# print(Fore.RED + 'Error!') — red
# print(Fore.YELLOW + 'Warning') — yellowمكتبة Rich لمخرجات طرفية أكثر ثراءً
توفر مكتبة rich عرض Markdown وكتل التعليمات البرمجية المميّزة بناءً على الصياغة والجداول ومؤشرات الانتظار في الطرفية. وهي تتكامل جيدًا مع مخرجات الوكيل المتدفقة.
# pip install rich
from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
console = Console()
def stream_with_rich(messages: list, client):
full_text = ''
with Live(console=console, refresh_per_second=10) as live:
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True
)
for chunk in stream:
token = chunk.choices[0].delta.content or ''
full_text += token
# Render accumulated text as Markdown in real time
live.update(Markdown(full_text))
return full_textالبث مع استدعاءات الأدوات
عند الجمع بين البث واستدعاء الدوال، يتم أيضًا بث الحقل tool_calls على أجزاء. اجمعوا سلسلة JSON عبر الأجزاء قبل تحليلها.
import json
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def stream_with_tools(messages: list, tools: list) -> dict:
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
tools=tools,
stream=True
)
tool_call_chunks = {}
for chunk in stream:
delta = chunk.choices[0].delta
if delta.tool_calls:
for tc in delta.tool_calls:
idx = tc.index
if idx not in tool_call_chunks:
tool_call_chunks[idx] = {'name': '', 'args': ''}
if tc.function.name:
tool_call_chunks[idx]['name'] += tc.function.name
if tc.function.arguments:
tool_call_chunks[idx]['args'] += tc.function.arguments
# Parse accumulated tool calls
return {v['name']: json.loads(v['args']) for v in tool_call_chunks.values()}عرض عدّاد الرموز
اعرضوا عدّادًا مباشرًا للرموز أثناء البث لمساعدة المستخدمين على مراقبة الاستخدام وفهم التكاليف. يتضمن بث OpenAI بيانات الاستخدام في الجزء الأخير عند تعيين stream_options={'include_usage': True}.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def stream_with_token_count(messages: list):
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=messages,
stream=True,
stream_options={'include_usage': True}
)
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end='', flush=True)
# Last chunk includes usage
if chunk.usage:
print(f'\n[Tokens: prompt={chunk.usage.prompt_tokens}, '
f'completion={chunk.usage.completion_tokens}, '
f'total={chunk.usage.total_tokens}]')أفضل ممارسات البث
ملخص لأفضل ممارسات بث المخرجات لوكلاء CLI:
- استخدموا دائمًا
flush=Trueأوsys.stdout.flush()لمنع التخزين المؤقت - اجمعوا الرموز في سلسلة نصية لتخزينها بعد البث
- تحقّقوا من
finish_reasonلاكتشاف الاقتطاع - استخدموا ألوان ANSI أو
richلتحسين الوضوح البصري - عالجوا بث استدعاءات الأدوات بجمع أجزاء وسائط JSON
اختبار المعرفة: بث المخرجات
اختبروا مدى فهمكم لبث المخرجات في وكلاء CLI.
مراجعة: بث المخرجات في وكلاء CLI
يمكنكم الآن إنشاء وكلاء CLI للبث يتسمون بالاستجابة وسهولة الاستخدام:
- مرروا
stream=Trueلتمكين البث من OpenAI SDK - استخدموا
print(token, end='', flush=True)لعرض الرموز المميزة فورًا - اجمعوا الرموز المميزة في سلسلة نصية لمعالجتها بعد انتهاء البث
- تحققوا من
finish_reasonفي الجزء الأخير لاكتشاف الاقتطاع - استخدموا
async forمعAsyncOpenAIللوكلاء غير المتزامنين - أضيفوا ألوان ANSI أو
richللحصول على تجربة طرفية متقنة
الأسئلة الشائعة
هل درس «تدفق المخرجات في وكلاء CLI» مجاني؟
نعم — نص درس «تدفق المخرجات في وكلاء CLI» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.
ماذا ستتعلم في «تدفق المخرجات في وكلاء CLI»؟
طباعة الرموز المتدفقة حرفًا حرفًا في واجهات الطرفية تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟
لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «تدفق المخرجات في وكلاء CLI»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟
نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- بناء واجهات وكلاء لسطر الأوامر
- وكلاء تفاعليون بنمط REPL
- تحليل الوسائط ونص التعليمات
- تدفق المخرجات في وكلاء CLI