trustgraph/docs/tech-specs/streaming-llm-responses.he.md
Alex Jenkins 8954fa3ad7 Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support
that dynamically loads language strings. You can test and use
different languages by simply passing the --lang flag (e.g., --lang
es for Spanish, --lang ru for Russian) or by configuring your
environment's LANG variable.

Automated Docs Translations: This PR introduces autonomously
translated Markdown documentation into several target languages,
including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew,
Arabic, Simplified Chinese, and Russian.
2026-04-14 12:08:32 +01:00

578 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: default
title: "מפרט טכני לתגובות LLM בסטרימינג"
parent: "Hebrew (Beta)"
---
# מפרט טכני לתגובות LLM בסטרימינג
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
## סקירה כללית
מפרט זה מתאר את יישום התמיכה בסטרימינג עבור תגובות LLM
ב-TrustGraph. סטרימינג מאפשר העברה בזמן אמת של טוקנים שנוצרו
ככל שהם מיוצרים על ידי ה-LLM, במקום לחכות להשלמת יצירת
התגובה.
יישום זה תומך בתרחישי שימוש הבאים:
1. **ממשקי משתמש בזמן אמת**: העברת טוקנים לממשק המשתמש בזמן יצירתם,
תוך מתן משוב ויזואלי מיידי.
2. **זמן עד לטוקן הראשון מופחת**: המשתמש רואה את הפלט מיד
ולא מחכה ליצירה מלאה.
3. **טיפול בתגובות ארוכות**: טיפול בפלטים ארוכים מאוד שעלולים
אחרת לגרום לחריגה מהזמן או לחרוג ממגבלות הזיכרון.
4. **יישומים אינטראקטיביים**: אפשור ממשקי צ'אט וסוכנים מגיבים.
## מטרות
**תאימות לאחור**: לקוחות קיימים שאינם משתמשים בסטרימינג ממשיכים
לעבוד ללא שינוי.
**עיצוב API עקבי**: סטרימינג ולא סטרימינג משתמשים באותם דפוסי
סכימה עם סטייה מינימלית.
**גמישות ספק**: תמיכה בסטרימינג כאשר הוא זמין, מעבר חלק
כאשר הוא אינו זמין.
**פריסה מדורגת**: יישום הדרגתי להפחתת סיכונים.
**תמיכה מקצה לקצה**: סטרימינג מספק ה-LLM דרך ליישומי לקוח
באמצעות Pulsar, Gateway API ו-Python API.
## רקע
### ארכיטקטורה נוכחית
זרימת השלמת הטקסט הנוכחית של ה-LLM פועלת באופן הבא:
1. לקוח שולח `TextCompletionRequest` עם שדות `system` ו-`prompt`.
2. שירות ה-LLM מעבד את הבקשה וממתין להשלמת היצירה.
3. `TextCompletionResponse` יחיד מוחזר עם מחרוזת `response` מלאה.
סכימה נוכחית (`trustgraph-base/trustgraph/schema/services/llm.py`):
```python
class TextCompletionRequest(Record):
system = String()
prompt = String()
class TextCompletionResponse(Record):
error = Error()
response = String()
in_token = Integer()
out_token = Integer()
model = String()
```
### מגבלות נוכחיות
**השהייה (Latency)**: משתמשים חייבים לחכות לסיום יצירת התוכן לפני שהם רואים פלט כלשהו.
**סיכון לחריגת זמן (Timeout)**: יצירת תוכן ארוכה עלולה לחרוג מספי זמן המוגדר בלקוח.
**חוויית משתמש ירודה (Poor UX)**: היעדר משוב במהלך היצירה יוצר תחושה של איטיות.
**שימוש במשאבים**: תגובות מלאות חייבות להיות מאוחסנות בזיכרון.
מפרט זה מתייחס למגבלות אלה על ידי אפשור העברת תגובה הדרגתית תוך שמירה על תאימות מלאה לאחור.
## עיצוב טכני
### שלב 1: תשתית
שלב 1 מקיים את הבסיס להעברה באמצעות שינוי סכימות, ממשקי API וכלי שורת פקודה.
#### שינויים בסכימה
##### סכימת LLM (`trustgraph-base/trustgraph/schema/services/llm.py`)
**שינויים בבקשה:**
```python
class TextCompletionRequest(Record):
system = String()
prompt = String()
streaming = Boolean() # NEW: Default false for backward compatibility
```
`streaming`: כאשר `true`, מבקשים משלוח תגובה בסטרימינג.
ברירת מחדל: `false` (ההתנהגות הקיימת נשמרת).
**שינויים בתגובה:**
```python
class TextCompletionResponse(Record):
error = Error()
response = String()
in_token = Integer()
out_token = Integer()
model = String()
end_of_stream = Boolean() # NEW: Indicates final message
```
`end_of_stream`: כאשר `true`, מציין שזו התגובה הסופית (או היחידה).
עבור בקשות שאינן סטרימינג: תגובה יחידה עם `end_of_stream=true`.
עבור בקשות סטרימינג: מספר תגובות, כולן עם `end_of_stream=false`.
מלבד התגובה האחרונה.
##### סכימת הפרומפט (`trustgraph-base/trustgraph/schema/services/prompt.py`)
שירות הפרומפט עוטף השלמת טקסט, ולכן הוא משקף את אותו דפוס:
**שינויים בבקשה:**
```python
class PromptRequest(Record):
id = String()
terms = Map(String())
streaming = Boolean() # NEW: Default false
```
**שינויים בתגובה:**
```python
class PromptResponse(Record):
error = Error()
text = String()
object = String()
end_of_stream = Boolean() # NEW: Indicates final message
```
#### שינויים בממשק ה-Gateway API
ממשק ה-Gateway API חייב לחשוף יכולות סטרימינג ללקוחות HTTP/WebSocket.
**עדכונים לממשק ה-REST API:**
`POST /api/v1/text-completion`: קבלת פרמטר `streaming` בגוף הבקשה
התנהגות התגובה תלויה בדגל הסטרימינג:
`streaming=false`: תגובת JSON בודדת (ההתנהגות הנוכחית)
`streaming=true`: זרם Server-Sent Events (SSE) או הודעות WebSocket
**פורמט תגובה (סטרימינג):**
כל חלק בזרם עוקב אחר מבנה הסכימה זהה:
```json
{
"response": "partial text...",
"end_of_stream": false,
"model": "model-name"
}
```
חלק אחרון:
```json
{
"response": "final text chunk",
"end_of_stream": true,
"in_token": 150,
"out_token": 500,
"model": "model-name"
}
```
#### שינויים בממשק ה-API של Python
ממשק ה-API של הלקוח ב-Python חייב לתמוך הן במצב סטרימינג והן במצב לא-סטרימינג
תוך שמירה על תאימות לאחור.
**עדכונים ל-LlmClient** (`trustgraph-base/trustgraph/clients/llm_client.py`):
```python
class LlmClient(BaseClient):
def request(self, system, prompt, timeout=300, streaming=False):
"""
Non-streaming request (backward compatible).
Returns complete response string.
"""
# Existing behavior when streaming=False
async def request_stream(self, system, prompt, timeout=300):
"""
Streaming request.
Yields response chunks as they arrive.
"""
# New async generator method
```
**עדכונים עבור PromptClient** (`trustgraph-base/trustgraph/base/prompt_client.py`):
דפוס דומה עם הפרמטר `streaming` וגרסה אסינכרונית של מחולל.
#### שינויים בכלי שורת הפקודה
**tg-invoke-llm** (`trustgraph-cli/trustgraph/cli/invoke_llm.py`):
```
tg-invoke-llm [system] [prompt] [--no-streaming] [-u URL] [-f flow-id]
```
הפעלת סטרימינג כברירת מחדל לשיפור חוויית משתמש אינטראקטיבית.
הדגל `--no-streaming` משבית את הסטרימינג.
כאשר הסטרימינג מופעל: פלט טוקנים לפלט סטנדרטי כשהם מגיעים.
כאשר הסטרימינג אינו מופעל: ממתינים לתגובה מלאה, ולאחר מכן מבצעים פלט.
**tg-invoke-prompt** (`trustgraph-cli/trustgraph/cli/invoke_prompt.py`):
```
tg-invoke-prompt [template-id] [var=value...] [--no-streaming] [-u URL] [-f flow-id]
```
אותו דפוס כמו `tg-invoke-llm`.
#### שינויים במחלקת הבסיס של שירות מודל שפה גדול (LLM).
**LlmService** (`trustgraph-base/trustgraph/base/llm_service.py`):
```python
class LlmService(FlowProcessor):
async def on_request(self, msg, consumer, flow):
request = msg.value()
streaming = getattr(request, 'streaming', False)
if streaming and self.supports_streaming():
async for chunk in self.generate_content_stream(...):
await self.send_response(chunk, end_of_stream=False)
await self.send_response(final_chunk, end_of_stream=True)
else:
response = await self.generate_content(...)
await self.send_response(response, end_of_stream=True)
def supports_streaming(self):
"""Override in subclass to indicate streaming support."""
return False
async def generate_content_stream(self, system, prompt, model, temperature):
"""Override in subclass to implement streaming."""
raise NotImplementedError()
```
--
### שלב 2: הוכחת היתכנות של VertexAI
שלב 2 מיישם סטרימינג בספק יחיד (VertexAI) כדי לאמת את
התשתית ולאפשר בדיקות מקצה לקצה.
#### יישום VertexAI
**מודול:** `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py`
**שינויים:**
1. החלפה של `supports_streaming()` כדי להחזיר `True`
2. יישום מחולל אסינכרוני `generate_content_stream()`
3. טיפול גם במודלים של Gemini וגם של Claude (דרך ממשק ה-API של VertexAI Anthropic)
**סטרימינג של Gemini:**
```python
async def generate_content_stream(self, system, prompt, model, temperature):
model_instance = self.get_model(model, temperature)
response = model_instance.generate_content(
[system, prompt],
stream=True # Enable streaming
)
for chunk in response:
yield LlmChunk(
text=chunk.text,
in_token=None, # Available only in final chunk
out_token=None,
)
# Final chunk includes token counts from response.usage_metadata
```
**קלוד (דרך VertexAI של חברת Anthropic) - סטרימינג:**
```python
async def generate_content_stream(self, system, prompt, model, temperature):
with self.anthropic_client.messages.stream(...) as stream:
for text in stream.text_stream:
yield LlmChunk(text=text)
# Token counts from stream.get_final_message()
```
#### בדיקות
בדיקות יחידה עבור הרכבת תגובות סטרימינג
בדיקות אינטגרציה עם VertexAI (Gemini ו-Claude)
בדיקות מקצה לקצה: CLI -> Gateway -> Pulsar -> VertexAI -> חזרה
בדיקות תאימות לאחור: בקשות שאינן סטרימינג עדיין עובדות
--
### שלב 3: כל ספקי מודלי שפה גדולים (LLM)
שלב 3 מרחיב את תמיכת הסטרימינג לכל ספקי מודלי השפה הגדולים במערכת.
#### סטטוס יישום ספק
כל ספק חייב לבצע אחת מהפעולות הבאות:
1. **תמיכה מלאה בסטרימינג**: ליישם `generate_content_stream()`
2. **מצב תאימות**: לטפל בדגל `end_of_stream` בצורה נכונה
(להחזיר תגובה בודדת עם `end_of_stream=true`)
| ספק | חבילה | תמיכה בסטרימינג |
|----------|---------|-------------------|
| OpenAI | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Claude/Anthropic | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Ollama | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Cohere | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Mistral | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Azure OpenAI | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| Google AI Studio | trustgraph-flow | מלא (ממשק סטרימינג מקורי) |
| VertexAI | trustgraph-vertexai | מלא (שלב 2) |
| Bedrock | trustgraph-bedrock | מלא (ממשק סטרימינג מקורי) |
| LM Studio | trustgraph-flow | מלא (תואם ל-OpenAI) |
| LlamaFile | trustgraph-flow | מלא (תואם ל-OpenAI) |
| vLLM | trustgraph-flow | מלא (תואם ל-OpenAI) |
| TGI | trustgraph-flow | מצומצם |
| Azure | trustgraph-flow | מצומצם |
#### תבנית יישום
עבור ספקים התואמים ל-OpenAI (OpenAI, LM Studio, LlamaFile, vLLM):
```python
async def generate_content_stream(self, system, prompt, model, temperature):
response = await self.client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": system},
{"role": "user", "content": prompt}
],
temperature=temperature,
stream=True
)
async for chunk in response:
if chunk.choices[0].delta.content:
yield LlmChunk(text=chunk.choices[0].delta.content)
```
--
### שלב 4: ממשק API של הסוכן
שלב 4 מרחיב את הסטרימינג לממשק ה-API של הסוכן. זה מורכב יותר מכיוון שה-
ממשק ה-API של הסוכן הוא כבר מטבעו רב-הודעות (מחשבה → פעולה → תצפית
→ חזור → תשובה סופית).
#### הסכימה הנוכחית של הסוכן
```python
class AgentStep(Record):
thought = String()
action = String()
arguments = Map(String())
observation = String()
user = String()
class AgentRequest(Record):
question = String()
state = String()
group = Array(String())
history = Array(AgentStep())
user = String()
class AgentResponse(Record):
answer = String()
error = Error()
thought = String()
observation = String()
```
#### שינויים מוצעים בסכימת הסוכן
**בקשות לשינויים:**
```python
class AgentRequest(Record):
question = String()
state = String()
group = Array(String())
history = Array(AgentStep())
user = String()
streaming = Boolean() # NEW: Default false
```
**שינויים בתגובה:**
הסוכן מייצר סוגים שונים של פלט במהלך מחזור החשיבה שלו:
מחשבות (היגיון)
פעולות (קריאות לכלי)
תצפיות (תוצאות של כלי)
תשובה (תגובה סופית)
שגיאות
מכיוון ש-`chunk_type` מציין איזה סוג תוכן נשלח, השדות הנפרדים
`answer`, `error`, `thought` ו-`observation` יכולים להיות מקובצים לשדה
`content` יחיד:
```python
class AgentResponse(Record):
chunk_type = String() # "thought", "action", "observation", "answer", "error"
content = String() # The actual content (interpretation depends on chunk_type)
end_of_message = Boolean() # Current thought/action/observation/answer is complete
end_of_dialog = Boolean() # Entire agent dialog is complete
```
**סמנטיקה של שדות:**
`chunk_type`: מציין איזה סוג תוכן נמצא בשדה `content`
`"thought"`: חשיבה/היגיון של הסוכן
`"action"`: כלי/פעולה המופעלת
`"observation"`: תוצאה מהפעלת הכלי
`"answer"`: תשובה סופית לשאלה של המשתמש
`"error"`: הודעת שגיאה
`content`: התוכן המועבר בפועל, המפורש בהתאם ל-`chunk_type`
`end_of_message`: כאשר `true`, סוג החלק הנוכחי הושלם
דוגמה: כל הטוקנים עבור המחשבה הנוכחית נשלחו
מאפשר ללקוחות לדעת מתי לעבור לשלב הבא
`end_of_dialog`: כאשר `true`, האינטראקציה כולה של הסוכן הושלמה
זו ההודעה האחרונה בזרם
#### התנהגות סטרימינג של הסוכן
כאשר `streaming=true`:
1. **סטרימינג של מחשבות:**
מספר חלקים עם `chunk_type="thought"`, `end_of_message=false`
החלק האחרון של המחשבה מכיל `end_of_message=true`
2. **הודעת פעולה:**
חלק יחיד עם `chunk_type="action"`, `end_of_message=true`
3. **תצפית:**
חלק/ים עם `chunk_type="observation"`, האחרון מכיל `end_of_message=true`
4. **חזור** על שלבים 1-3 כאשר הסוכן מסיק מסקנות
5. **תשובה סופית:**
`chunk_type="answer"` עם התגובה הסופית ב-`content`
החלק האחרון מכיל `end_of_message=true`, `end_of_dialog=true`
**רצף סטרימינג לדוגמה:**
```
{chunk_type: "thought", content: "I need to", end_of_message: false, end_of_dialog: false}
{chunk_type: "thought", content: " search for...", end_of_message: true, end_of_dialog: false}
{chunk_type: "action", content: "search", end_of_message: true, end_of_dialog: false}
{chunk_type: "observation", content: "Found: ...", end_of_message: true, end_of_dialog: false}
{chunk_type: "thought", content: "Based on this", end_of_message: false, end_of_dialog: false}
{chunk_type: "thought", content: " I can answer...", end_of_message: true, end_of_dialog: false}
{chunk_type: "answer", content: "The answer is...", end_of_message: true, end_of_dialog: true}
```
כאשר `streaming=false`:
התנהגות נוכחית נשמרת
תגובה אחת עם תשובה מלאה
`end_of_message=true`, `end_of_dialog=true`
#### שער (Gateway) ו-API בפייתון
שער: נקודת קצה חדשה של SSE/WebSocket עבור סטרימינג של סוכן
API בפייתון: שיטת גנרטור אסינכרונית חדשה `agent_stream()`
--
## שיקולי אבטחה
**ללא נקודות תורפה חדשות**: סטרימינג משתמש באותה אימות/הרשאה
**הגבלת קצב**: יש להחיל מגבלות קצב פר-טוקן או פר-חלק במידת הצורך
**טיפול בחיבורים**: יש לסיים חיבורים בצורה תקינה בעת ניתוק הלקוח
**ניהול תזמון**: בקשות סטרימינג דורשות טיפול מתאים בתזמון
## שיקולי ביצועים
**זיכרון**: סטרימינג מפחית את השימוש בזיכרון המקסימלי (ללא אחסון מלא של התגובה)
**השהיה**: זמן עד לקבלת הטוקן הראשון קטן משמעותית
**תקורה של חיבורים**: לחיבורי SSE/WebSocket יש תקורה של שמירה על חיבור פעיל
**תפוקת Pulsar**: מספר הודעות קטנות לעומת הודעה גדולה אחת
פשרה
## אסטרטגיית בדיקות
### בדיקות יחידה
סריאליזציה/דה-סריאליזציה של סכימה עם שדות חדשים
תאימות לאחור (שדות חסרים משתמשים בערכי ברירת מחדל)
לוגיקת הרכבת חלקים
### בדיקות אינטגרציה
יישום הסטרימינג של כל ספק מודלי שפה גדולים (LLM)
נקודות קצה של סטרימינג של API בשער
שיטות סטרימינג של לקוח בפייתון
### בדיקות מקצה לקצה
פלט סטרימינג של כלי שורת הפקודה (CLI)
זרימה מלאה: לקוח → שער → Pulsar → LLM → חזרה
עומסי עבודה מעורבים של סטרימינג/לא סטרימינג
### בדיקות תאימות לאחור
לקוחות קיימים עובדים ללא שינוי
בקשות לא סטרימינג מתנהגות באופן זהה
## תוכנית מעבר
### שלב 1: תשתית
פריסת שינויי סכימה (תואמת לאחור)
פריסת עדכוני API בשער
פריסת עדכוני API בפייתון
שחרור עדכוני כלי שורת הפקודה
### שלב 2: VertexAI
הטמעת יישום סטרימינג של VertexAI
אימות באמצעות עומסי עבודה לבדיקה
### שלב 3: כל הספקים
הטמעת עדכוני ספק באופן הדרגתי
ניטור לאיתור בעיות
### שלב 4: ממשק API של סוכן
הטמעת שינויים בסכימת הסוכן
הטמעת יישום סטרימינג של סוכן
עדכון התיעוד
## ציר זמן
| שלב | תיאור | תלויות |
|-------|-------------|--------------|
| שלב 1 | תשתית | אין |
| שלב 2 | הוכחת היתכנות של VertexAI | שלב 1 |
| שלב 3 | כל הספקים | שלב 2 |
| שלב 4 | ממשק API של סוכן | שלב 3 |
## החלטות עיצוב
השאלות הבאות נפתרו במהלך המפרט:
1. **ספירת טוקנים בסטרימינג**: ספירת הטוקנים היא הפרשים, ולא סכומים מצטברים.
צרכנים יכולים לחבר אותם אם יש צורך. זה תואם לאופן שבו רוב הספקים מדווחים
על שימוש ומפשט את היישום.
2. **טיפול בשגיאות בזרמים**: אם מתרחשת שגיאה, השדה `error` מאוכלס ושאר השדות אינם נחוצים. שגיאה היא תמיד ההודעה האחרונה - אסור לשלוח או לצפות להודעות נוספות לאחר מכן.
שגיאה. עבור זרמי מודלים שפתיים (LLM) / הנחיות, `end_of_stream=true`. עבור זרמי סוכנים,
`chunk_type="error"` עם `end_of_dialog=true`.
3. **התאוששות מתגובה חלקית**: פרוטוקול העברת ההודעות (Pulsar) עמיד,
ולכן אין צורך בניסיונות חוזרים ברמת ההודעה. אם לקוח מאבד את המעקב אחר הזרם
או מתנתק, עליו לנסות שוב את כל הבקשה מההתחלה.
4. **שירות מהיר עם סטרימינג**: סטרימינג נתמך רק עבור טקסט (`text`)
תשובות, ולא עבור תשובות מובנות (`object`). שירות הפרומפט יודע מראש
האם הפלט יהיה JSON או טקסט, בהתבסס על תבנית הפרומפט. אם מתבצעת
בקשת סטרימינג עבור פרומפט שפלטו הוא JSON, אז...
השירות צריך או:
להחזיר את קובץ ה-JSON השלם בתגובה אחת עם `end_of_stream=true`, או
לדחות את בקשת הסטרימינג עם שגיאה
## שאלות פתוחות
אין כרגע.
## הפניות
סכימת מודל שפה גדול (LLM) נוכחית: `trustgraph-base/trustgraph/schema/services/llm.py`
סכימת הנחיה נוכחית: `trustgraph-base/trustgraph/schema/services/prompt.py`
סכימת סוכן נוכחית: `trustgraph-base/trustgraph/schema/services/agent.py`
שירות LLM בסיסי: `trustgraph-base/trustgraph/base/llm_service.py`
ספק VertexAI: `trustgraph-vertexai/trustgraph/model/text_completion/vertexai/llm.py`
ממשק API של שער: `trustgraph-base/trustgraph/api/`
כלי שורת פקודה: `trustgraph-cli/trustgraph/cli/`