Observability در هوش مصنوعی چیست؟ راهنمای مانیتورینگ مدلها، Agentها و APIهای هوش مصنوعی
AI Observability به شما کمک میکند عملکرد، هزینه، Latency، خطا و کیفیت مدلها و Agentهای هوش مصنوعی را بررسی کنید. در این راهنما، طراحی Logs، Metrics، Traces، Dashboard و Alerting را با نمونهکد و API درواره میآموزید.
مقدمه
در یک نرمافزار معمولی، موفقیت درخواست اغلب با معیارهایی مانند وضعیت HTTP، زمان پاسخ و نرخ خطا سنجیده میشود. اگر سرور کد 200 برگرداند و پاسخ در زمان مناسبی دریافت شود، احتمالاً عملیات موفق بوده است.
اما در یک اپلیکیشن هوش مصنوعی، دریافت کد 200 لزوماً به معنای موفقیت نیست.
ممکن است مدل:
- پاسخ نامرتبط تولید کند؛
- اطلاعات نادرست بسازد؛
- از دستور اصلی پیروی نکند؛
- JSON نامعتبر برگرداند؛
- ابزار اشتباهی را انتخاب کند؛
- سند نامرتبطی را در سیستم RAG استفاده کند؛
- پاسخ را بهدلیل محدودیت Token نیمهکاره رها کند؛
- هزینهای بسیار بیشتر از مقدار مورد انتظار ایجاد کند؛
- در مقایسه با نسخه قبلی Prompt کیفیت پایینتری داشته باشد؛
- یا با وجود پاسخ فنی موفق، مسئله کاربر را حل نکند.
به همین دلیل، مانیتورینگ سنتی برای سیستمهای مبتنی بر مدلهای زبانی کافی نیست. باید علاوه بر سلامت زیرساخت، رفتار مدل، کیفیت پاسخ، مسیر Agent، مصرف Token، هزینه، Retrieval، Tool Calling و تجربه واقعی کاربر را نیز مشاهده و ارزیابی کنیم.
AI Observability برای پاسخدادن به همین نیاز بهوجود آمده است.
فهرست مطالب
- AI Observability چیست؟
- تفاوت Monitoring و Observability
- چرا مانیتورینگ سنتی برای AI کافی نیست؟
- سه لایه Observability در سیستمهای AI
- Logs، Metrics و Traces
- طراحی Trace برای درخواست هوش مصنوعی
- چه دادههایی باید ثبت شوند؟
- مانیتورینگ Latency و Streaming
- مانیتورینگ Token و هزینه
- مانیتورینگ خطا، Retry و Fallback
- Observability در RAG
- Observability در Tool Calling
- مانیتورینگ AI Agentها
- اندازهگیری کیفیت پاسخ
- Hallucination و Groundedness
- Online Evaluation و Offline Evaluation
- طراحی Dashboard
- Alerting و Alert Fatigue
- حریم خصوصی و امنیت Logها
- نمونهکد Python با API درواره
- نمونهکد TypeScript
- OpenTelemetry در اپلیکیشنهای AI
- SLI، SLO و SLA
- چکلیست Production
- پرسشهای متداول
- جمعبندی
AI Observability چیست؟
AI Observability یا مشاهدهپذیری هوش مصنوعی مجموعهای از روشها، دادهها و ابزارها برای درک رفتار داخلی یک سیستم مبتنی بر مدل هوش مصنوعی از طریق خروجیهای قابلاندازهگیری آن است.
این خروجیها میتوانند شامل موارد زیر باشند:
- Logs
- Metrics
- Traces
- Prompt و نسخه آن
- مدل و ارائهدهنده
- Input Tokens و Output Tokens
- Cached Tokens
- Latency و Time to First Token
- Tool Calls
- Retrieval Results
- مسیر اجرای Agent
- هزینه
- خطاها
- امتناع مدل از پاسخگویی
- نتایج ارزیابی کیفیت
- بازخورد کاربر
هدف AI Observability فقط این نیست که بدانیم «سیستم روشن است یا خاموش». باید بتوانیم به سؤالهای عمیقتری پاسخ دهیم:
- چرا این پاسخ اشتباه بود؟
- کدام Prompt این پاسخ را تولید کرد؟
- کدام مدل و ارائهدهنده استفاده شد؟
- چه اسنادی از RAG بازیابی شدند؟
- Agent چرا این ابزار را انتخاب کرد؟
- کدام مرحله بیشترین زمان را مصرف کرد؟
- چرا هزینه امروز دو برابر شده است؟
- چند درصد پاسخهای JSON نامعتبر بودهاند؟
- آیا Fallback کیفیت پاسخ را کاهش داده است؟
- آیا مدل جدید از نسخه قبلی بهتر است؟
- کدام کاربران بیشترین خطای Rate Limit را دریافت میکنند؟
- آیا پاسخهای فارسی یک مدل کیفیت پایینتری دارند؟
- آیا تغییر Chunking باعث بهبود Retrieval شده است؟
OpenTelemetry، Observability را توانایی درک وضعیت داخلی یک سیستم از طریق بررسی خروجیهای آن تعریف میکند و دادههای Telemetry را معمولاً در قالب Logs، Metrics و Traces سازمان میدهد. راهنمای Observability در OpenTelemetry
تفاوت Monitoring و Observability
Monitoring و Observability به یکدیگر مرتبطاند، اما دقیقاً یکسان نیستند.
Monitoring
Monitoring معمولاً بر مجموعهای از سؤالهای از قبل شناختهشده تمرکز دارد:
- نرخ خطا چقدر است؟
- CPU چقدر مصرف شده؟
- چند درخواست در دقیقه داریم؟
- Latency از آستانه عبور کرده است؟
- Queue چند Job دارد؟
- سرویس در دسترس است؟
Observability
Observability باید امکان بررسی سؤالهایی را فراهم کند که شاید هنگام طراحی سیستم پیشبینی نشده بودند:
- چرا فقط درخواستهای فارسی مدل خاصی کند شدهاند؟
- چرا Agent بعد از Fallback ابزار متفاوتی انتخاب کرده است؟
- چرا هزینه افزایش یافته اما تعداد درخواست ثابت مانده است؟
- کدام سند باعث پاسخ نادرست شده؟
- چرا پاسخهای تولیدشده با Prompt نسخه جدید طولانیترند؟
- کدام مسیر Agent بیشترین Retry را دارد؟
| ویژگی | Monitoring | Observability |
|---|---|---|
| تمرکز | وضعیتهای شناختهشده | تحلیل رفتار داخلی |
| سؤالها | از قبل تعریفشده | شناختهشده و ناشناخته |
| دادهها | Metrics و Alerts | Logs، Metrics، Traces و Context |
| خروجی | تشخیص وجود مشکل | بررسی علت مشکل |
| کاربرد در AI | سلامت سرویس | سلامت، هزینه و کیفیت سیستم |
Monitoring بخشی از Observability است، اما Observability دامنه گستردهتری دارد.
چرا مانیتورینگ سنتی برای AI کافی نیست؟
در نرمافزار قطعی، یک ورودی مشخص معمولاً خروجی مشخصی تولید میکند. اما مدلهای هوش مصنوعی احتمالاتیاند و رفتار آنها میتواند با عوامل مختلف تغییر کند:
- مدل
- نسخه مدل
- System Prompt
- تاریخچه مکالمه
- Temperature
- Context
- اسناد RAG
- خروجی ابزار
- ترتیب پیامها
- Provider
- محدودیت Token
- سیاستهای ایمنی
برای مثال، درخواست زیر ممکن است از نظر زیرساخت کاملاً موفق باشد:
{
"status": 200,
"latency_ms": 2150
}
اما پاسخ مدل ممکن است اطلاعات نادرستی داشته باشد:
مهلت بازپرداخت شما ۳۰ روز است.
درحالیکه سند رسمی شرکت مهلت را هفت روز اعلام کرده است.
از دید Monitoring سنتی:
- API موفق بوده است.
- Latency مناسب است.
- خطای سرور وجود ندارد.
از دید AI Observability:
- پاسخ Grounded نیست.
- مدل از سند صحیح استفاده نکرده است.
- احتمالاً Retrieval یا Prompt مشکل دارد.
- پاسخ میتواند به تجربه مشتری و کسبوکار آسیب بزند.
بنابراین یک سیستم هوش مصنوعی حداقل باید در سه سطح مشاهده شود:
- سلامت زیرساخت
- عملکرد مدل و Workflow
- کیفیت نتیجه کسبوکار
سه لایه AI Observability
لایه زیرساخت
این لایه مشابه Observability نرمافزارهای معمولی است:
- CPU
- Memory
- Network
- Connection Pool
- Queue Depth
- Database Latency
- Cache Hit Rate
- HTTP Error Rate
- Availability
لایه مدل و Workflow
این لایه رفتار AI را بررسی میکند:
- مدل و ارائهدهنده
- Prompt Version
- Context Size
- Token Usage
- Latency
- Time to First Token
- Tool Calls
- Retry
- Fallback
- Finish Reason
- Validation Result
- Retrieval Results
- Agent Steps
لایه کیفیت و کسبوکار
این لایه بررسی میکند آیا سیستم واقعاً هدف خود را محقق کرده است:
- Task Completion Rate
- Answer Relevance
- Groundedness
- Accuracy
- User Satisfaction
- Ticket Deflection
- Escalation Rate
- Conversion Rate
- Cost per Successful Task
- Human Correction Rate
فقط زمانی تصویر کاملی از سیستم داریم که این سه لایه به یکدیگر متصل باشند.
سه سیگنال اصلی: Logs، Metrics و Traces
Logs
Log یک رکورد از رویداد مشخص است:
{
"event": "ai_request_completed",
"request_id": "req_2048",
"model": "MODEL_ID",
"input_tokens": 1350,
"output_tokens": 420,
"latency_ms": 2870,
"status": "success"
}
Logs برای بررسی جزئیات یک رخداد خاص مناسباند.
Metrics
Metric یک مقدار عددی است که در طول زمان اندازهگیری میشود:
ai_requests_total
ai_request_duration_seconds
ai_input_tokens_total
ai_output_tokens_total
ai_request_cost
ai_validation_failures_total
Metrics برای Dashboard، روندها و Alerting مناسباند.
Traces
Trace مسیر کامل یک درخواست را میان اجزای سیستم نشان میدهد:
POST /v1/chat
├── authenticate
├── check_wallet
├── retrieve_documents
├── rerank_documents
├── build_context
├── call_model
├── validate_output
└── record_usage
هر بخش Trace یک Span نامیده میشود. Span میتواند زمان شروع، پایان، وضعیت، Attribute و Eventهای خود را داشته باشد.
OpenTelemetry برای عملیات Generative AI نیز Semantic Conventionهایی در زمینه مدل، Tokenها، ابزارها، Retrieval و زمان اولین Chunk توسعه داده است تا ثبت Telemetry میان سیستمها هماهنگتر شود. Semantic Conventions در OpenTelemetry
Event چیست؟
Event رخدادی است که درون یک Span اتفاق میافتد:
Span: provider.request
Events:
- request_sent
- first_token_received
- retry_started
- response_completed
Event برای ثبت اتفاقهای مهم بدون ایجاد Span جداگانه مفید است.
طراحی Trace برای درخواست هوش مصنوعی
یک Trace مناسب باید مسیر واقعی درخواست را نشان دهد، نه فقط فراخوانی مدل را.
ai.request
├── auth.validate
├── rate_limit.check
├── billing.precheck
├── memory.load
├── rag.query_rewrite
├── rag.vector_search
├── rag.rerank
├── prompt.build
├── router.select_model
├── provider.chat_completion
├── output.validate
├── safety.check
├── billing.record_usage
└── response.send
این ساختار به شما اجازه میدهد بفهمید:
- آیا کندی از مدل بوده یا RAG؟
- آیا Rate Limit پیش از تماس با Provider عمل کرده؟
- آیا مدل اصلی یا Fallback استفاده شده؟
- آیا Validation باعث Retry شده؟
- آیا ثبت مصرف بعد از پاسخ شکست خورده؟
- آیا Context Builder بیشازحد زمان مصرف کرده؟
Attributeهای Trace
نمونه Attributeهای مناسب:
{
"request.id": "req_2048",
"user.id_hash": "usr_91f...",
"organization.id": "org_52",
"gen_ai.request.model": "MODEL_ID",
"gen_ai.provider.name": "provider_a",
"gen_ai.request.stream": true,
"gen_ai.request.temperature": 0.2,
"gen_ai.request.max_tokens": 1200,
"prompt.version": "support-v7",
"context.version": "ctx-v3",
"route.fallback_used": false
}
از مقدار Hashشده یا شناسه داخلی بهجای اطلاعات شخصی مستقیم استفاده کنید.
چه دادههایی باید برای هر درخواست ثبت شوند؟
هویت و ارتباط درخواست
- Internal Request ID
- Trace ID
- Provider Request ID
- Session ID
- Conversation ID
- Job ID
- شناسه Hashشده کاربر
- شناسه سازمان
- Endpoint
اطلاعات مدل
- مدل درخواستشده
- مدل واقعی پاسخدهنده
- ارائهدهنده
- Region
- قابلیت درخواستشده
- حالت Streaming
- Temperature
max_tokens- Response Format
Prompt و Context
- Prompt Name
- Prompt Version
- Context Builder Version
- تعداد پیامها
- Token تخمینی Context
- شناسه اسناد بازیابیشده
- شناسه حافظههای استفادهشده
- فهرست ابزارهای ارائهشده
- Hash محتوای Prompt
در محیطهای حساس بهتر است متن کامل Prompt بهطور پیشفرض ثبت نشود.
نتیجه
- Response ID
- Finish Reason
- Refusal Status
- Validation Status
- Tool Calls
- Input Tokens
- Output Tokens
- Cached Tokens
- Latency
- Time to First Token
- Retry Count
- Fallback Route
- هزینه
- HTTP Status
- Error Code
کیفیت
- User Feedback
- Relevance Score
- Groundedness Score
- Safety Result
- Human Review
- Task Completion
- Correction Required
Request ID و Trace ID
این دو شناسه نقش متفاوتی دارند.
Request ID
برای شناسایی درخواست از دید API شما استفاده میشود:
req_2048
Trace ID
مسیر درخواست را در چند سرویس و عملیات مرتبط میکند:
4bf92f3577b34da6a3ce929d0e0e4736
یک Request میتواند Trace واحدی داشته باشد که چندین Span داخل آن قرار گرفتهاند.
اگر Provider نیز Request ID برمیگرداند، آن را جداگانه ثبت کنید:
{
"internal_request_id": "req_2048",
"trace_id": "4bf92f...",
"provider_request_id": "upstream_8821"
}
این ارتباط برای بررسی مشکلات Billing، Timeout و پشتیبانی بسیار مهم است.
مانیتورینگ Latency
یک مقدار کلی برای Latency کافی نیست. بهتر است زمان هر مرحله جداگانه ثبت شود.
End-to-End Latency
از ورود درخواست کاربر تا تکمیل پاسخ.
Provider Latency
زمان فراخوانی مدل.
Retrieval Latency
زمان جستوجو و بازیابی اسناد.
Reranking Latency
زمان رتبهبندی دوباره نتایج.
Tool Latency
زمان اجرای ابزار.
Validation Latency
زمان Parse و اعتبارسنجی خروجی.
Queue Wait Time
مدت انتظار Job پیش از شروع پردازش.
Time to First Token
در Streaming، مدتزمان از ارسال درخواست تا دریافت اولین Token یا Chunk.
Inter-Token Latency
فاصله زمانی میان Chunkهای پاسخ.
Time to Last Token
زمان تکمیل کل خروجی.
Streaming معمولاً زمان کل تولید را کاهش نمیدهد، اما زمان دریافت اولین بخش پاسخ را کمتر و تجربه کاربری را بهتر میکند. راهنمای Production API و Streaming
چرا p50، p95 و p99 مهماند؟
میانگین میتواند مشکلات واقعی را پنهان کند.
فرض کنید:
- ۹۰ درخواست در دو ثانیه پاسخ گرفتهاند.
- ۱۰ درخواست در ۳۰ ثانیه پاسخ گرفتهاند.
میانگین شاید قابلقبول به نظر برسد، اما ۱۰ درصد کاربران تجربه بسیار ضعیفی داشتهاند.
p50
نیمی از درخواستها سریعتر از این مقدار تکمیل شدهاند.
p95
۹۵ درصد درخواستها سریعتر از این مقدار تکمیل شدهاند.
p99
۹۹ درصد درخواستها سریعتر از این مقدار تکمیل شدهاند.
برای بررسی تجربه کاربران کندتر، p95 و p99 اهمیت زیادی دارند.
مانیتورینگ Streaming
در Streaming فقط ثبت زمان پاسخ نهایی کافی نیست.
Metricهای مهم:
- Time to First Chunk
- Stream Duration
- Number of Chunks
- Stream Completion Rate
- Client Disconnect Rate
- Provider Disconnect Rate
- Incomplete Stream Rate
- Tokens per Second
- Final Usage Received Rate
در Chat Completions سازگار با OpenAI میتوان در مدلهای پشتیبانیشده با گزینه زیر دریافت Usage نهایی را درخواست کرد:
{
"stream": true,
"stream_options": {
"include_usage": true
}
}
Usage معمولاً در Chunk نهایی قرار میگیرد. اگر Stream قطع یا لغو شود، ممکن است Chunk نهایی Usage دریافت نشود. مرجع Streaming Chat Completions
بنابراین سیستم Billing نباید بدون برنامه جایگزین، فقط به Chunk نهایی وابسته باشد.
وضعیتهای پیشنهادی Streaming
started
first_chunk_received
streaming
completed
client_disconnected
provider_disconnected
timed_out
cancelled
incomplete
مانیتورینگ Token
Tokenها مستقیماً روی هزینه، Latency و Rate Limit اثر میگذارند.
Metricهای ضروری:
- Input Tokens
- Output Tokens
- Total Tokens
- Cached Input Tokens
- Cache Creation Tokens
- Reasoning Tokens، در صورت گزارش
- Tokens per Request
- Tokens per User
- Tokens per Organization
- Tokens per Model
- Tokens per Feature
- Tokens per Successful Task
نسبت ورودی به خروجی
Input/Output Ratio =
Input Tokens / Output Tokens
اگر این نسبت بسیار بالا باشد، ممکن است Context بیشازحد بزرگ باشد.
Context Utilization
اگر دائماً Context بزرگی ارسال میشود اما فقط بخش کوچکی از آن برای پاسخ لازم است، RAG، Memory یا Context Builder نیاز به بهینهسازی دارد.
Finish Reason
این فیلد باید مانیتور شود:
stop
length
tool_calls
content_filter
اگر نرخ length افزایش یابد، ممکن است:
max_tokensبسیار کم باشد؛- Prompt پاسخ طولانی درخواست کند؛
- مدل بیشازحد توضیح دهد؛
- Schema خروجی با ظرفیت سازگار نباشد.
مانیتورینگ هزینه
صرفاً ثبت تعداد Token کافی نیست؛ باید هزینه واقعی نیز محاسبه و تحلیل شود.
هزینه هر درخواست
Request Cost =
Input Token Cost
+ Output Token Cost
+ Cache Cost
+ Tool Cost
+ Retrieval Cost
هزینه هر کاربر
User Cost =
Sum of Request Costs for User
هزینه هر قابلیت
برای مثال:
Chat: 35%
Document Analysis: 25%
Image Generation: 20%
Agent Workflows: 15%
Embeddings: 5%
هزینه هر وظیفه موفق
این معیار از هزینه هر درخواست مفیدتر است:
Cost per Successful Task =
Total Cost / Successful Tasks
ممکن است مدل ارزانتر Retry و خطای بیشتری داشته باشد و درنهایت هزینه هر وظیفه موفق آن از مدل قویتر بیشتر شود.
Budget Variance
Budget Variance =
Actual Cost - Estimated Cost
اختلاف زیاد میان هزینه تخمینی و واقعی میتواند نشاندهنده مشکلات زیر باشد:
- تخمین نادرست Token
- خروجی بسیار طولانی
- Retry پنهان SDK
- Fallback پرهزینه
- تغییر قیمت مدل
- خطای Billing
- Tool Callهای تکراری
هشدار هزینه
نمونه Alertها:
- افزایش ۵۰ درصدی هزینه ساعتی
- هزینه یک درخواست بیشتر از سقف
- مصرف روزانه کاربر خارج از الگو
- افزایش ناگهانی Output Tokens
- کاهش Cache Hit Rate
- افزایش Retry و Fallback
مانیتورینگ خطا
خطاها را فقط با status=failed ثبت نکنید. باید طبقهبندی شوند.
خطاهای Client
invalid_request
authentication_failed
permission_denied
context_too_large
model_not_found
unsupported_parameter
خطاهای محدودیت و Billing
rate_limit_exceeded
token_limit_exceeded
insufficient_balance
budget_exceeded
concurrency_limit_exceeded
خطاهای Provider
provider_timeout
provider_connection_error
provider_rate_limit
provider_5xx
provider_invalid_response
خطاهای خروجی
empty_response
incomplete_response
json_parse_failed
schema_validation_failed
tool_arguments_invalid
content_refused
خطاهای Workflow
tool_failed
agent_max_steps_reached
fallback_exhausted
queue_expired
job_cancelled
طبقهبندی ثابت خطاها امکان مقایسه مدلها و ارائهدهندگان را فراهم میکند.
مانیتورینگ Retry
برای Retry این موارد را ثبت کنید:
- دلیل Retry
- شماره تلاش
- فاصله Backoff
- مسیر Retry
- نتیجه نهایی
- Token و هزینه هر تلاش
- Retry داخلی یا اپلیکیشنی
- Deadline باقیمانده
Metricهای مهم:
retry_rate
average_attempts_per_request
retry_success_rate
cost_added_by_retries
latency_added_by_retries
افزایش Retry Rate ممکن است اولین نشانه اختلال Provider باشد، حتی اگر درخواستها درنهایت موفق شوند.
مانیتورینگ Fallback
برای هر Fallback ثبت کنید:
{
"fallback_used": true,
"primary_route": "provider_a/model_x",
"fallback_route": "provider_b/model_y",
"fallback_reason": "provider_timeout",
"primary_attempt_cost": 0.012,
"fallback_cost": 0.018
}
Metricهای مهم:
- Fallback Rate
- Fallback Success Rate
- Fallback Latency
- Fallback Cost
- Quality after Fallback
- Capability Mismatch Rate
اگر فقط موفقیت فنی Fallback را بسنجیم، ممکن است کاهش کیفیت نادیده بماند. باید کیفیت پاسخ مسیر اصلی و جایگزین نیز مقایسه شود.
Observability در سیستمهای RAG
در RAG پاسخ نهایی فقط محصول مدل نیست. کیفیت به چند مرحله وابسته است:
Query
→ Query Rewriting
→ Retrieval
→ Filtering
→ Reranking
→ Context Assembly
→ Generation
اگر پاسخ اشتباه باشد، باید بفهمیم مشکل در کدام مرحله بوده است.
دادههای Retrieval
برای هر جستوجو ثبت کنید:
- Query اصلی
- Query بازنویسیشده
- Embedding Model
- Index Version
- Chunking Version
- Filterها
top_k- شناسه اسناد
- Retrieval Score
- Reranking Score
- رتبه نهایی
- تعداد Chunk
- Tokenهای Context
- Latency هر مرحله
نمونه:
{
"retrieval": {
"query_hash": "q_91f...",
"index_version": "kb-v12",
"chunking_version": "chunk-v4",
"top_k": 8,
"returned_documents": [
{
"document_id": "doc_14",
"chunk_id": "chunk_8",
"retrieval_score": 0.83,
"rerank_score": 0.91,
"final_rank": 1
}
],
"latency_ms": 185
}
}
Retrieval Precision
چه تعداد از Chunkهای بازیابیشده واقعاً مرتبط بودهاند؟
Retrieval Precision =
Relevant Retrieved Chunks / All Retrieved Chunks
Retrieval Recall
آیا اطلاعات لازم در میان Chunkهای بازیابیشده حضور داشته است؟
Retrieval Recall =
Retrieved Relevant Chunks / All Relevant Chunks
برای محاسبه دقیق Recall به Dataset دارای Ground Truth نیاز دارید.
Context Relevance
آیا Context واردشده به مدل برای سؤال کاربر مرتبط است؟
Groundedness
آیا پاسخ مدل توسط اسناد بازیابیشده پشتیبانی میشود؟
Citation Correctness
اگر پاسخ منبع دارد:
- آیا Citation واقعاً ادعا را پشتیبانی میکند؟
- آیا شناسه سند درست است؟
- آیا مدل به سندی اشاره کرده که در Context حضور داشته است؟
- آیا متن منبع قدیمی یا منقضی است؟
علتهای رایج شکست RAG
- Query Rewriting اشتباه
- Chunking نامناسب
- Metadata ناقص
- فیلتر دسترسی اشتباه
top_kبسیار کم یا زیاد- Reranker ضعیف
- سند قدیمی
- Context بیشازحد بزرگ
- Prompt نامناسب
- مدل ناتوان در استفاده از Context
Trace باید تشخیص این علتها را ممکن کند.
Observability در Tool Calling
در Tool Calling باید هر مرحله ثبت شود:
- ابزارهای در دسترس
- ابزار انتخابشده
- دلیل یا Context انتخاب
- Tool Call ID
- آرگومانها
- نتیجه Validation
- مجوز کاربر
- زمان اجرا
- وضعیت نتیجه
- تعداد Retry
- Idempotency Key
- خروجی خلاصهشده
- خطای ابزار
نمونه:
{
"tool_call": {
"id": "call_2048",
"name": "get_transaction_status",
"arguments_schema_valid": true,
"authorization_passed": true,
"latency_ms": 340,
"status": "success",
"result_size_bytes": 420
}
}
Tool Selection Accuracy
آیا مدل ابزار درست را انتخاب کرده است؟
Tool Argument Accuracy
آیا آرگومانها صحیح و کامل بودهاند؟
Tool Success Rate
چه درصدی از Tool Callها با موفقیت اجرا شدهاند؟
Unnecessary Tool Call Rate
چه تعداد Tool Call بدون نیاز انجام شدهاند؟
این معیار از نظر هزینه و ایمنی مهم است.
Tool Loop Rate
Agent چند بار ابزار یکسان را بدون پیشرفت تکرار کرده است؟
search → search → search → search
افزایش این Metric میتواند نشانه Prompt نامناسب، ابزار مبهم یا نبود معیار پایان باشد.
مانیتورینگ AI Agentها
برای Agent فقط ورودی و خروجی نهایی کافی نیست. باید Trajectory یا مسیر اجرای آن نیز مشاهده شود.
Trajectory میتواند شامل موارد زیر باشد:
1. Goal received
2. Plan created
3. Search tool called
4. Document retrieved
5. Database tool called
6. Permission denied
7. Alternative action selected
8. Final response generated
Metricهای مهم Agent
- Task Completion Rate
- Average Steps per Task
- Maximum Steps Reached Rate
- Tool Calls per Task
- Tool Failure Rate
- Repeated Action Rate
- Human Escalation Rate
- Agent Cancellation Rate
- Cost per Task
- Latency per Task
- Successful Recovery Rate
- Unsafe Action Attempt Rate
طول مسیر همیشه معیار کیفیت نیست
Agent با مراحل کمتر ممکن است کارآمدتر باشد، اما ممکن است بررسی ضروری را انجام نداده باشد. Agent با مراحل بیشتر نیز ممکن است دقیقتر یا گرفتار Loop باشد.
بنابراین باید مسیر واقعی با مسیر مورد انتظار مقایسه شود. ارزیابی Trajectory بررسی میکند چه مراحل ضروری انجام شده و ترتیب یا نتیجه آنها چگونه بوده است. راهنمای ارزیابی Agent در LangSmith
پایان Agent
دلیل پایان را ثبت کنید:
completed
user_cancelled
max_steps_reached
max_cost_reached
timeout
tool_failure
permission_denied
safety_blocked
fallback_exhausted
اندازهگیری کیفیت پاسخ
کیفیت پاسخ یک مقدار واحد نیست. باید براساس کاربرد به چند معیار تقسیم شود.
Relevance
آیا پاسخ به سؤال کاربر مرتبط است؟
Correctness
آیا پاسخ از نظر واقعیت یا پاسخ مرجع صحیح است؟
Groundedness
آیا ادعاها توسط Context یا اسناد تأیید میشوند؟
Completeness
آیا تمام بخشهای مهم سؤال پاسخ داده شدهاند؟
Instruction Following
آیا مدل قالب، زبان و محدودیتهای Prompt را رعایت کرده است؟
Format Validity
آیا JSON یا خروجی ساختاریافته معتبر است؟
Safety
آیا پاسخ با سیاستهای امنیتی و محتوایی سازگار است؟
Tone
آیا لحن برای کاربرد موردنظر مناسب است؟
Task Success
آیا هدف واقعی کاربر تکمیل شده است؟
ممکن است پاسخ از نظر نگارشی عالی باشد، اما مسئله کاربر را حل نکند. به همین دلیل Task Success معمولاً از معیارهای زبانی عمومی مهمتر است.
Hallucination چگونه مانیتور میشود؟
تشخیص کامل Hallucination بهصورت خودکار دشوار است، اما میتوان سیگنالهایی ایجاد کرد.
مقایسه پاسخ با Context
ادعاهای پاسخ استخراج و با اسناد ارائهشده مقایسه شوند.
الزام Citation
مدل برای هر ادعای مهم منبع مشخص کند.
بررسی Citation
صرف وجود Citation کافی نیست؛ باید مشخص شود منبع واقعاً ادعا را پشتیبانی میکند.
قوانین قطعی
مقادیر حساس با دیتابیس یا کد بررسی شوند:
if response_amount != database_amount:
flag_for_review()

LLM-as-a-Judge
مدل دیگری پاسخ را ارزیابی میکند. این روش مقیاسپذیر است، اما کامل و بیطرف نیست.
بازبینی انسانی
نمونهای از پاسخها توسط انسان بررسی شوند، بهخصوص:
- حوزههای حساس
- پاسخهای با Confidence پایین
- مدل یا Prompt جدید
- شکایت کاربران
- Tool Callهای مهم
LLM-as-a-Judge چیست؟
در این روش یک مدل، خروجی مدل دیگر را براساس Rubric ارزیابی میکند:
{
"score": 4,
"label": "mostly_correct",
"reason": "پاسخ صحیح است اما محدودیت اصلی را ذکر نکرده است."
}
مزایا
- مقیاسپذیر
- مناسب تحلیل حجم زیاد
- قابلاستفاده در Online Evaluation
- انعطافپذیر برای معیارهای مختلف
محدودیتها
- امکان سوگیری
- حساسیت به Prompt ارزیابی
- ناپایداری
- هزینه اضافی
- احتمال ترجیح سبک خاص
- نیاز به Calibration با ارزیابی انسانی
امتیاز Judge نباید حقیقت قطعی تلقی شود. باید با Dataset انسانی مقایسه و کالیبره شود.
ارزیابی قطعی و احتمالاتی
ارزیابی قطعی
با کد قابلانجام است:
- JSON معتبر است؟
- فیلد ضروری وجود دارد؟
- Citation به سند واقعی اشاره میکند؟
- مبلغ منفی نیست؟
- Tool مجاز بوده؟
- خروجی از طول مجاز عبور کرده؟
- زبان پاسخ درست است؟
ارزیابی احتمالاتی
معمولاً با مدل یا انسان انجام میشود:
- آیا پاسخ مفید است؟
- آیا توضیح کافی است؟
- آیا پاسخ Grounded است؟
- آیا لحن مناسب است؟
- آیا مسئله کاربر حل شده است؟
ابتدا باید معیارهای قطعی ارزان و قابلاعتماد اجرا شوند و سپس فقط در موارد لازم از Judge استفاده شود.
Online Evaluation و Offline Evaluation
Offline Evaluation
پیش از انتشار روی Dataset ثابت اجرا میشود:
Prompt v6 + Model A
در مقابل
Prompt v7 + Model B
کاربردها:
- مقایسه مدلها
- تست Prompt جدید
- ارزیابی RAG
- Regression Testing
- تعیین Threshold
Online Evaluation
روی بخشی از درخواستهای واقعی Production اجرا میشود:
- ارزیابی کیفیت نمونه پاسخها
- تشخیص تغییر رفتار
- تحلیل شکایتها
- Drift Detection
- پایش ایمنی
LangSmith نیز Online Evaluation را برای بررسی الگوهای کیفیت، ایمنی و رفتار واقعی Production از روی Traceها از Offline Evaluation جدا میکند. مفاهیم Evaluation در LangSmith
Sampling
ارزیابی تمام درخواستها ممکن است گران یا از نظر حریم خصوصی نامناسب باشد.
نمونه راهبرد:
۱۰۰٪ درخواستهای خطادار
۱۰۰٪ Tool Callهای حساس
۲۰٪ پاسخهای مدل جدید
۵٪ ترافیک عادی
۱٪ پاسخهای پایدار و کمخطر
Human Feedback
بازخورد کاربر یکی از مهمترین سیگنالهاست:
👍 مفید بود
👎 مفید نبود
اما بازخورد دودویی اطلاعات محدودی دارد. بهتر است دلیل نیز قابلانتخاب باشد:
نادرست بود
نامرتبط بود
کامل نبود
خیلی طولانی بود
منبع معتبر نداشت
درخواست را انجام نداد
نکته درباره Feedback
نبود بازخورد به معنای رضایت نیست. بسیاری از کاربران هیچ واکنشی ثبت نمیکنند.
سیگنالهای ضمنی نیز مفیدند:
- بازنویسی فوری سؤال
- درخواست پاسخ دوباره
- ترک مکالمه
- Copyکردن پاسخ
- بازکردن Citation
- ارجاع به اپراتور انسانی
- اصلاح دستی خروجی
- Undoکردن اقدام Agent
طراحی Dashboard برای AI Observability
یک Dashboard خوب باید امکان حرکت از نمای کلی به Trace دقیق را فراهم کند.
نمای سلامت کلی
- درخواست در دقیقه
- Success Rate
- Error Rate
- p95 Latency
- Time to First Token
- هزینه ساعتی
- Active Streams
- Queue Depth
- Fallback Rate
- Validation Failure Rate
نمای مدلها
| مدل | درخواست | موفقیت | p95 Latency | میانگین Token | هزینه | کیفیت |
|---|---|---|---|---|---|---|
| Model A | ۱۰٬۲۴۰ | ۹۹٫۲٪ | ۴٫۸s | ۱٬۴۲۰ | متغیر | ۴٫۳ |
| Model B | ۷٬۸۲۰ | ۹۸٫۷٪ | ۲٫۹s | ۱٬۱۰۰ | متغیر | ۴٫۰ |
نمای ارائهدهندگان
- Availability
- Timeout Rate
5xx- Rate Limit
- Latency
- Circuit State
- Fallback In
- Fallback Out
نمای هزینه
- هزینه امروز
- هزینه به تفکیک مدل
- هزینه به تفکیک کاربر
- هزینه به تفکیک قابلیت
- Cost per Successful Task
- Retry Cost
- Fallback Cost
- Cache Savings
نمای کیفیت
- User Satisfaction
- Groundedness
- Retrieval Relevance
- JSON Validity
- Tool Success
- Hallucination Flags
- Human Escalation
- Model Comparison
Drill-down
با کلیک روی هر Metric باید بتوان به موارد زیر رسید:
Dashboard
→ Filtered Requests
→ Individual Trace
→ Spans
→ Retrieval Documents
→ Tool Calls
→ Sanitized Input and Output
Alerting
Alert باید عملی و قابلپیگیری باشد.
Alert نامناسب:
یک درخواست خطا داد.
Alert مناسب:
نرخ Timeout مدل اصلی طی ۵ دقیقه از ۲٪ به ۱۴٪ رسیده و p95 Latency از ۸ ثانیه عبور کرده است.
Alertهای زیرساخت
- Error Rate بالا
- Latency بالا
- Queue Depth زیاد
- Database Failure
- Circuit Open
- Connection Pool Exhausted
Alertهای هزینه
- هزینه بیشتر از بودجه
- افزایش غیرعادی Token
- کاهش Cache Hit Rate
- Retry Cost بالا
- مصرف غیرعادی کاربر
Alertهای کیفیت
- افزایش Validation Failure
- کاهش Groundedness
- افزایش Feedback منفی
- افزایش Tool Failure
- افزایش Max Steps
- افزایش Human Escalation
جلوگیری از Alert Fatigue
اگر تیم دائماً Alertهای بیاهمیت دریافت کند، هشدارهای واقعی نیز نادیده گرفته میشوند.
راهکارها:
- Alert براساس بازه زمانی
- استفاده از p95 و نرخ بهجای یک رخداد
- Deduplication
- Grouping براساس مدل و Provider
- Severity
- Cooldown
- لینک مستقیم به Dashboard و Runbook
- مشخصبودن مسئول Alert
سطحهای Severity
INFO: فقط ثبت
WARNING: نیاز به بررسی در ساعات کاری
HIGH: پاسخ سریع
CRITICAL: اختلال گسترده یا خطر مالی و امنیتی
SLI، SLO و SLA در سرویسهای AI
SLI
شاخص اندازهگیریشده:
- Availability
- Error Rate
- p95 Latency
- Stream Completion Rate
- Task Completion Rate
- Output Validation Rate
- Groundedness Rate
SLO
هدف داخلی سرویس:
۹۹٫۵٪ درخواستهای معتبر بدون خطای زیرساختی تکمیل شوند.
۹۵٪ پاسخهای Streaming در کمتر از ۲ ثانیه شروع شوند.
۹۹٪ خروجیهای ساختاریافته از Validation عبور کنند.
SLA
تعهد رسمی و قراردادی به مشتری است و ممکن است پیامد مالی یا حقوقی داشته باشد.
Error Budget
اگر SLO برابر ۹۹٫۹٪ باشد، میزان شکست مجاز محدود است. Error Budget کمک میکند میان انتشار قابلیت جدید و پایداری تعادل برقرار شود.
در سیستم AI بهتر است SLO فقط براساس HTTP Status نباشد. پاسخ فنی موفق اما غیرقابلاستفاده نباید موفقیت کامل محسوب شود.
حریم خصوصی در AI Observability
ثبت Prompt و Completion برای Debug مفید است، اما ممکن است شامل اطلاعات حساس باشد:
- نام و شماره تماس
- اطلاعات مالی
- دادههای پزشکی
- اسناد محرمانه
- API Key
- رمز عبور
- قرارداد
- کد اختصاصی
- اطلاعات سازمانی
اصل حداقلسازی داده
فقط اطلاعاتی را ثبت کنید که برای هدف مشخص لازماند.
بهجای متن کامل:
{
"prompt_hash": "sha256:...",
"prompt_chars": 4820,
"message_count": 8,
"prompt_version": "support-v7"
}
Redaction
پیش از ذخیره Log:
09123456789 → [PHONE]
user@example.com → [EMAIL]
sk-secret-key → [API_KEY]
Hash شناسه کاربر
import hashlib
import hmac
def hash_user_id(user_id: str, secret: bytes) -> str:
return hmac.new(
secret,
user_id.encode(),
hashlib.sha256,
).hexdigest()
HMAC با Secret از Hash ساده برای شناسههای قابلحدس مناسبتر است.
دسترسی به Trace
همه اعضای تیم نباید محتوای کامل Trace را ببینند. دسترسی باید براساس نقش باشد:
Support: Metadata محدود
Engineering: Trace فنی
Security: Audit و Incident
Finance: Usage و Cost
Admin محدود: محتوای Redacted
Retention
برای انواع داده زمان نگهداری تعریف کنید:
Metrics تجمیعی: بلندمدت
Logs فنی: ۳۰ تا ۹۰ روز
Promptهای Redacted: کوتاهمدت
محتوای حساس: ثبت نشود یا حداقل نگهداری
Audit عملیات حساس: طبق سیاست سازمان
Opt-in برای محتوای کامل
ثبت کامل Prompt و Completion بهتر است فقط در محیط Debug کنترلشده یا با سیاست روشن انجام شود.
OpenTelemetry نیز ثبت محتوای کامل پیام، Tool Call و Tool Result را مسئلهای Opt-in در نظر میگیرد؛ زیرا این دادهها میتوانند حساس و پرحجم باشند. Observability مولد با OpenTelemetry
نمونهکد Python با API درواره
نصب وابستگیها
pip install -U openai opentelemetry-api opentelemetry-sdk
تنظیم Client و Tracer
import os
import time
import uuid
from openai import OpenAI
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("darvareh-ai-service")
client = OpenAI(
api_key=os.environ["DARVAREH_API_KEY"],
base_url="https://api.darvareh.ir/v1",
)
ConsoleSpanExporter فقط برای نمونه است. در Production معمولاً Traceها از طریق OpenTelemetry Collector به Backend مشاهدهپذیری ارسال میشوند.
فراخوانی مدل با Trace
def generate_answer(
user_message: str,
model: str,
prompt_version: str,
) -> str:
request_id = f"req_{uuid.uuid4().hex}"
with tracer.start_as_current_span(
"ai.chat_request"
) as root_span:
root_span.set_attribute(
"app.request.id",
request_id,
)
root_span.set_attribute(
"gen_ai.request.model",
model,
)
root_span.set_attribute(
"app.prompt.version",
prompt_version,
)
with tracer.start_as_current_span(
"provider.chat_completion"
) as provider_span:
started_at = time.monotonic()
try:
response = client.chat.completions.create(
model=model,
messages=[
{
"role": "system",
"content": (
"شما یک دستیار فنی دقیق هستید. "
"اگر اطلاعات کافی نیست، حدس نزنید."
),
},
{
"role": "user",
"content": user_message,
},
],
temperature=0.2,
max_tokens=800,
)
latency_ms = int(
(time.monotonic() - started_at) * 1000
)
provider_span.set_attribute(
"app.latency_ms",
latency_ms,
)
provider_span.set_attribute(
"gen_ai.response.model",
response.model or model,
)
if response.id:
provider_span.set_attribute(
"gen_ai.response.id",
response.id,
)
choice = response.choices[0]
finish_reason = choice.finish_reason or "unknown"
provider_span.set_attribute(
"gen_ai.response.finish_reason",
finish_reason,
)
if response.usage:
provider_span.set_attribute(
"gen_ai.usage.input_tokens",
response.usage.prompt_tokens,
)
provider_span.set_attribute(
"gen_ai.usage.output_tokens",
response.usage.completion_tokens,
)
provider_span.set_attribute(
"gen_ai.usage.total_tokens",
response.usage.total_tokens,
)
content = choice.message.content
if not content:
provider_span.set_status(
trace.Status(
trace.StatusCode.ERROR,
"empty_response",
)
)
raise ValueError("Model returned no content")
provider_span.set_status(
trace.Status(
trace.StatusCode.OK
)
)
return content
except Exception as error:
provider_span.record_exception(error)
provider_span.set_status(
trace.Status(
trace.StatusCode.ERROR,
type(error).__name__,
)
)
raise
چرا متن Prompt ثبت نشد؟
در این نمونه فقط نسخه Prompt، مدل، مصرف و زمان ثبت شدهاند. متن کاربر ممکن است شامل اطلاعات حساس باشد. در صورت نیاز، نسخه Redacted یا Hash آن را ثبت کنید.
ثبت Metrics در Python
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
ConsoleMetricExporter,
PeriodicExportingMetricReader,
)
metric_reader = PeriodicExportingMetricReader(
ConsoleMetricExporter(),
export_interval_millis=10_000,
)
metrics.set_meter_provider(
MeterProvider(metric_readers=[metric_reader])
)
meter = metrics.get_meter("darvareh-ai-service")
request_counter = meter.create_counter(
"ai.requests",
description="Total number of AI requests",
)
input_token_counter = meter.create_counter(
"ai.input_tokens",
description="Total input tokens",
)
output_token_counter = meter.create_counter(
"ai.output_tokens",
description="Total output tokens",
)
latency_histogram = meter.create_histogram(
"ai.request.duration",
unit="ms",
description="AI request duration",
)
ثبت Metric:
attributes = {
"model": model,
"provider": "darvareh",
"status": "success",
}
request_counter.add(1, attributes)
input_token_counter.add(input_tokens, attributes)
output_token_counter.add(output_tokens, attributes)
latency_histogram.record(latency_ms, attributes)
مراقب Cardinality باشید
نباید Attributeهایی با تعداد مقادیر بسیار زیاد را روی Metrics قرار دهید:
نامناسب:
{"request_id": request_id}
مناسب:
{
"model": model,
"status": "success",
"endpoint": "chat_completions",
}
Request ID برای Trace و Log مناسب است، نه Metric تجمیعی.
نمونه Streaming با اندازهگیری TTFT
def stream_answer(user_message: str, model: str):
request_started = time.monotonic()
first_chunk_at = None
chunk_count = 0
final_usage = None
stream = client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": user_message,
}
],
stream=True,
stream_options={
"include_usage": True,
},
)
try:
for chunk in stream:
if first_chunk_at is None:
first_chunk_at = time.monotonic()
chunk_count += 1
if chunk.usage is not None:
final_usage = chunk.usage
if chunk.choices:
delta = chunk.choices[0].delta.content
if delta:
yield delta
finally:
completed_at = time.monotonic()
ttft_ms = (
int((first_chunk_at - request_started) * 1000)
if first_chunk_at is not None
else None
)
total_ms = int(
(completed_at - request_started) * 1000
)
print(
{
"event": "ai_stream_finished",
"model": model,
"ttft_ms": ttft_ms,
"total_ms": total_ms,
"chunk_count": chunk_count,
"usage_received": final_usage is not None,
}
)
پشتیبانی از include_usage و ساختار Chunkها باید برای مدل و ارائهدهنده انتخابی بررسی شود.
نمونهکد TypeScript
نصب وابستگیها
npm install openai \
@opentelemetry/api \
@opentelemetry/sdk-trace-node \
@opentelemetry/sdk-trace-base
تنظیم OpenTelemetry
import OpenAI from "openai";
import { trace, SpanStatusCode } from "@opentelemetry/api";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import {
BatchSpanProcessor,
ConsoleSpanExporter,
} from "@opentelemetry/sdk-trace-base";
const provider = new NodeTracerProvider({
spanProcessors: [
new BatchSpanProcessor(new ConsoleSpanExporter()),
],
});
provider.register();
const tracer = trace.getTracer("darvareh-ai-service");
const client = new OpenAI({
apiKey: process.env.DARVAREH_API_KEY,
baseURL: "https://api.darvareh.ir/v1",
});
فراخوانی مدل
async function generateAnswer({
userMessage,
model,
promptVersion,
}: {
userMessage: string;
model: string;
promptVersion: string;
}): Promise<string> {
return tracer.startActiveSpan(
"ai.chat_request",
async (rootSpan) => {
const requestId = crypto.randomUUID();
rootSpan.setAttributes({
"app.request.id": requestId,
"gen_ai.request.model": model,
"app.prompt.version": promptVersion,
});
try {
const result = await tracer.startActiveSpan(
"provider.chat_completion",
async (providerSpan) => {
const startedAt = performance.now();
try {
const response =
await client.chat.completions.create({
model,
messages: [
{
role: "system",
content:
"شما یک دستیار فنی دقیق هستید و حدس نمیزنید.",
},
{
role: "user",
content: userMessage,
},
],
temperature: 0.2,
max_tokens: 800,
});
providerSpan.setAttributes({
"app.latency_ms": Math.round(
performance.now() - startedAt,
),
"gen_ai.response.id": response.id,
"gen_ai.response.model":
response.model ?? model,
"gen_ai.response.finish_reason":
response.choices[0]?.finish_reason ??
"unknown",
});
if (response.usage) {
providerSpan.setAttributes({
"gen_ai.usage.input_tokens":
response.usage.prompt_tokens,
"gen_ai.usage.output_tokens":
response.usage.completion_tokens,
"gen_ai.usage.total_tokens":
response.usage.total_tokens,
});
}
const content =
response.choices[0]?.message?.content;
if (!content) {
throw new Error("Empty model response");
}
providerSpan.setStatus({
code: SpanStatusCode.OK,
});
return content;
} catch (error) {
providerSpan.recordException(
error as Error,
);
providerSpan.setStatus({
code: SpanStatusCode.ERROR,
message:
error instanceof Error
? error.message
: "Unknown error",
});
throw error;
} finally {
providerSpan.end();
}
},
);
rootSpan.setStatus({
code: SpanStatusCode.OK,
});
return result;
} catch (error) {
rootSpan.recordException(error as Error);
rootSpan.setStatus({
code: SpanStatusCode.ERROR,
});
throw error;
} finally {
rootSpan.end();
}
},
);
}
طراحی Schema برای Log
یک Schema ثابت امکان Query و تحلیل بهتر را فراهم میکند:
{
"timestamp": "2026-07-11T12:00:00Z",
"level": "info",
"event": "ai_request_completed",
"request_id": "req_2048",
"trace_id": "4bf92f...",
"user_id_hash": "usr_91f...",
"organization_id": "org_52",
"endpoint": "chat_completions",
"model_requested": "MODEL_ID",
"model_used": "MODEL_ID",
"provider": "darvareh",
"prompt_version": "support-v7",
"stream": false,
"input_tokens": 1420,
"output_tokens": 380,
"cached_tokens": 0,
"latency_ms": 2850,
"ttft_ms": null,
"retry_count": 0,
"fallback_used": false,
"finish_reason": "stop",
"validation_status": "passed",
"status": "success",
"error_code": null
}
نسخه Schema
ساختار Telemetry نیز باید نسخه داشته باشد:
{
"telemetry_schema_version": "1.2"
}
بدون Versioning، تغییر نام فیلدها میتواند Dashboard و Alertها را خراب کند.
Sampling در Tracing
ثبت تمام Traceها در ترافیک بالا هزینهبر است.
Head Sampling
در ابتدای درخواست تصمیم گرفته میشود Trace ذخیره شود یا نه.
مزیت:
- ساده
- هزینه کمتر
محدودیت:
- هنوز نمیدانیم درخواست خطا خواهد داد یا نه.
Tail Sampling
پس از مشاهده نتیجه تصمیم گرفته میشود Trace ذخیره شود.
میتوان این موارد را همیشه نگه داشت:
- خطاها
- Latency بالا
- Fallback
- Tool Call حساس
- Validation Failure
- هزینه غیرعادی
و فقط درصد کمی از درخواستهای عادی را ذخیره کرد.
Trace و Metric را به هم متصل کنید
Dashboard باید امکان رفتن از Metric به Trace را فراهم کند.
برای مثال:
Alert: p95 Latency بالا
→ Dashboard مدل
→ درخواستهای کند
→ Trace خاص
→ Span کند
→ Provider Request
OpenTelemetry با Context Propagation امکان مرتبطکردن Logs، Metrics و Traces را در مسیر درخواست فراهم میکند. مستندات OpenTelemetry
تشخیص Drift
Drift یعنی رفتار سیستم در طول زمان تغییر کند.
Model Drift
ارائهدهنده نسخه مدل را تغییر میدهد و خروجی متفاوت میشود.
Data Drift
نوع درخواست کاربران تغییر میکند.
Retrieval Drift
محتوای پایگاه دانش یا توزیع اسناد تغییر میکند.
Cost Drift
میانگین Token یا قیمت افزایش مییابد.
Quality Drift
امتیاز Groundedness یا رضایت کاربر کاهش پیدا میکند.
برای تشخیص Drift باید Baseline داشته باشید و Metricها را در طول زمان مقایسه کنید.
مقایسه نسخههای Prompt
برای هر پاسخ Prompt Version را ثبت کنید:
support-v6
support-v7
سپس مقایسه کنید:
| معیار | v6 | v7 |
|---|---|---|
| Task Success | ۸۱٪ | ۸۷٪ |
| Groundedness | ۸۸٪ | ۹۱٪ |
| Input Tokens | ۱٬۲۰۰ | ۱٬۵۵۰ |
| Output Tokens | ۴۵۰ | ۳۹۰ |
| p95 Latency | ۵٫۲s | ۵٫۸s |
| Cost per Task | کمتر | کمی بیشتر |
یک Prompt ممکن است کیفیت را بهتر کند اما هزینه و Latency را افزایش دهد. تصمیم باید براساس هدف کسبوکار باشد.
اشتباهات رایج در AI Observability
ثبت فقط HTTP Status
کد 200 چیزی درباره کیفیت پاسخ نمیگوید.
ثبت تمام Promptها بدون Redaction
ریسک حریم خصوصی و امنیت ایجاد میکند.
نداشتن Prompt Version
نمیتوان تغییر کیفیت را به نسخه مشخصی مرتبط کرد.
تمرکز فقط بر میانگین Latency
تجربه کاربران کندتر پنهان میشود.
نادیدهگرفتن Retryهای SDK
هزینه و Latency واقعی کمتر از مقدار ثبتشده به نظر میرسد.
ثبتنکردن مسیر Fallback
مشخص نیست پاسخ را کدام مدل تولید کرده است.
Metrics با Cardinality بالا
استفاده از Request ID، متن Prompt یا User ID بهعنوان Label متریک، هزینه و عملکرد سیستم Metrics را خراب میکند.
ارزیابی تمام درخواستها با مدل Judge
هزینه بالا و تأخیر غیرضروری ایجاد میکند.
یکیدانستن امتیاز Judge با حقیقت
Judge نیز یک مدل احتمالاتی است.
نداشتن Trace برای RAG و Tools
در صورت پاسخ اشتباه، علت واقعی قابلتشخیص نیست.
Dashboard بدون اقدام
Dashboard باید به تصمیم یا عملیات مشخصی منجر شود.
Alert بدون Runbook
تیم میفهمد مشکلی وجود دارد، اما نمیداند چه کاری انجام دهد.
Runbook چیست؟
Runbook دستورالعمل واکنش به یک Alert یا Incident است.
نمونه برای افزایش Timeout:
1. Dashboard Provider Latency را بررسی کن.
2. مدلها و Regionهای درگیر را مشخص کن.
3. Retry Rate و Circuit State را بررسی کن.
4. اگر فقط یک Provider مشکل دارد، مسیر را غیرفعال کن.
5. Fallback Success Rate و Cost را کنترل کن.
6. وضعیت را در کانال Incident ثبت کن.
7. پس از بازیابی، مسیر اصلی را تدریجی فعال کن.
چکلیست AI Observability برای Production
شناسایی و ارتباط
- هر درخواست Internal Request ID دارد.
- Trace ID در تمام سرویسها منتقل میشود.
- Provider Request ID ثبت میشود.
- Conversation و Job قابلردیابیاند.
- Prompt Version ثبت میشود.
- Context Builder Version ثبت میشود.
- Model Route و Fallback Route مشخصاند.
Latency
- End-to-End Latency ثبت میشود.
- Provider Latency جداست.
- Retrieval و Tool Latency ثبت میشوند.
- Time to First Token اندازهگیری میشود.
- p50، p95 و p99 موجودند.
- Queue Wait Time ثبت میشود.
- Stream Completion Rate اندازهگیری میشود.
Token و هزینه
- Input و Output Tokens ثبت میشوند.
- Cached Tokens در صورت وجود ثبت میشوند.
- هزینه هر درخواست محاسبه میشود.
- هزینه Retry و Fallback مشخص است.
- هزینه به تفکیک مدل، کاربر و قابلیت قابلمشاهده است.
- Cost per Successful Task اندازهگیری میشود.
- افزایش غیرعادی هزینه Alert دارد.
خطا و پایداری
- خطاها کد داخلی ثابت دارند.
- Provider Error از Client Error جداست.
- Retry Count و علت آن ثبت میشود.
- Fallback Rate قابلمشاهده است.
- Circuit Breaker State مانیتور میشود.
- Refusal و Incomplete Response ثبت میشوند.
- Validation Failure مانیتور میشود.
RAG
- Query و نسخه بازنویسی ثبت یا Hash میشوند.
- Index و Chunking Version ثبت میشود.
- شناسه اسناد بازیابیشده موجود است.
- Retrieval و Reranking Score ثبت میشوند.
- Context Token Count اندازهگیری میشود.
- Groundedness و Citation Correctness ارزیابی میشوند.
- دسترسی اسناد قابل Audit است.
Agent و Tool Calling
- مسیر Agent ثبت میشود.
- تعداد مراحل اندازهگیری میشود.
- Max Steps Rate مانیتور میشود.
- Tool Call ID موجود است.
- آرگومان و نتیجه Validation میشوند.
- مجوز اجرای Tool ثبت میشود.
- Tool Retry و Idempotency قابلردیابیاند.
- عملیات حساس Audit Log دارند.
کیفیت
- Dataset ارزیابی وجود دارد.
- Offline Eval پیش از انتشار اجرا میشود.
- Online Eval با Sampling انجام میشود.
- Feedback کاربر ثبت میشود.
- دلیل Feedback منفی قابلانتخاب است.
- Judge با ارزیابی انسانی کالیبره شده است.
- Drift مدل، داده و هزینه بررسی میشود.
امنیت و حریم خصوصی
- API Key و Secretها Log نمیشوند.
- Prompt کامل بهصورت پیشفرض ثبت نمیشود.
- داده حساس Redact میشود.
- شناسه کاربر Hash میشود.
- Traceها کنترل دسترسی دارند.
- Retention Policy مشخص است.
- Cache و Trace میان سازمانها جداست.
- حذف داده کاربر امکانپذیر است.
Dashboard و Alerting
- Dashboard سلامت کلی وجود دارد.
- نمای مدل و Provider جداست.
- Dashboard هزینه وجود دارد.
- Dashboard کیفیت و RAG وجود دارد.
- Alertها Severity دارند.
- Alertها Deduplicate میشوند.
- هر Alert Runbook و مسئول دارد.
- از Metric میتوان به Trace رسید.
پرسشهای متداول
AI Observability چیست؟
AI Observability مجموعهای از Logs، Metrics، Traces و ارزیابیهاست که به تیمها کمک میکند عملکرد، هزینه، خطا، کیفیت و رفتار مدلها، RAG و Agentهای هوش مصنوعی را درک کنند.
تفاوت Monitoring و Observability چیست؟
Monitoring وضعیتها و خطاهای شناختهشده را دنبال میکند. Observability امکان بررسی علت مشکلات و سؤالهای پیشبینینشده را از طریق ارتباط Logs، Metrics، Traces و دادههای کیفیت فراهم میکند.
مهمترین Metrics برای API هوش مصنوعی چیست؟
نرخ موفقیت، نرخ خطا، p95 Latency، Time to First Token، Input و Output Tokens، هزینه، Retry Rate، Fallback Rate، Validation Failure و Task Completion Rate از مهمترین معیارها هستند.
آیا باید Prompt و پاسخ کامل را Log کنیم؟
معمولاً نه. این دادهها ممکن است حساس و پرحجم باشند. بهتر است نسخه Prompt، Hash، Metadata و محتوای Redacted ثبت شود. ثبت کامل باید محدود، کنترلشده و براساس سیاست حریم خصوصی باشد.
Time to First Token چیست؟
مدتزمان میان ارسال درخواست و دریافت اولین Token یا Chunk در پاسخ Streaming است. این معیار تأثیر زیادی بر تجربه ادراکشده کاربر دارد.
چگونه هزینه هر درخواست را مانیتور کنیم؟
مصرف Input، Output و Cached Tokens را با قیمت همان مدل ترکیب کنید و هزینه Retry، Fallback، Toolها و Retrieval را نیز در صورت وجود اضافه کنید.
چگونه کیفیت RAG را اندازهگیری کنیم؟
با معیارهایی مانند Retrieval Precision، Retrieval Recall، Context Relevance، Groundedness و Citation Correctness میتوان کیفیت مراحل Retrieval و Generation را بررسی کرد.
چگونه Agent را مانیتور کنیم؟
هدف، مراحل اجرا، Tool Callها، آرگومانها، نتایج، خطاها، Retryها، تعداد مراحل، هزینه و دلیل پایان Agent را در یک Trace مرتبط ثبت کنید.
آیا LLM-as-a-Judge قابلاعتماد است؟
برای تحلیل در مقیاس بالا مفید است، اما حقیقت قطعی نیست. باید با Rubric دقیق، Dataset انسانی و Calibration استفاده شود.
OpenTelemetry چه کمکی میکند؟
OpenTelemetry یک چارچوب متنباز و مستقل از Vendor برای تولید و انتقال Logs، Metrics و Traces است. میتوان از آن برای مرتبطکردن مسیر درخواست AI در API، RAG، Provider، Toolها و سرویسهای داخلی استفاده کرد.
آیا Streaming نیز قابلمانیتور است؟
بله. Time to First Chunk، تعداد Chunkها، زمان کل، نرخ تکمیل، قطع Client و دریافت Usage نهایی از معیارهای مهم Streaming هستند.
آیا API درواره اطلاعات مصرف را برمیگرداند؟
پاسخ مدلهای متنی در رابط سازگار با OpenAI معمولاً میتواند شامل بخش usage باشد، اما جزئیات Usage و Cached Tokens به مدل و ارائهدهنده وابسته است. برنامه باید نبود یا تفاوت این فیلدها را نیز مدیریت کند.
جمعبندی
AI Observability یکی از پایههای ساخت سرویسهای هوش مصنوعی قابلاعتماد است. بدون مشاهدهپذیری، تیم فقط میداند کاربر پاسخ نامناسبی دریافت کرده، اما نمیتواند علت آن را میان Prompt، مدل، Provider، RAG، Memory، Tool و Fallback پیدا کند.
یک سیستم Observability مناسب باید بتواند:
- هر درخواست را از ابتدا تا انتها ردیابی کند؛
- مدل، ارائهدهنده و نسخه Prompt را مشخص کند؛
- Latency و Time to First Token را اندازه بگیرد؛
- Token و هزینه را ثبت کند؛
- Retry و Fallback را قابلمشاهده سازد؛
- مسیر RAG و Agent را در Trace نمایش دهد؛
- خروجیهای نامعتبر و Refusal را تشخیص دهد؛
- کیفیت پاسخ را با Eval و Feedback بررسی کند؛
- و همه این کارها را بدون افشای اطلاعات حساس انجام دهد.
هدف Observability جمعآوری بیشترین داده ممکن نیست. هدف جمعآوری دادهای است که به تشخیص مشکل، کاهش هزینه، بهبود کیفیت و تصمیمگیری سریعتر منجر شود.
مانیتورینگ سرویسهای هوش مصنوعی با API درواره
درواره زیرساخت دسترسی به مدلهای مختلف هوش مصنوعی را از طریق یک API سازگار با OpenAI فراهم میکند. توسعهدهندگان میتوانند اطلاعاتی مانند درخواستها، مصرف، مدل، Latency و خطاهای اپلیکیشن خود را ثبت و در کنار دادههای RAG، Tool Calling و Agentها تحلیل کنند.
آدرس پایه API درواره:
https://api.darvareh.ir/v1
برای ساخت یک معماری قابلاعتماد، Trace درخواست را از Backend خود آغاز کنید، فراخوانی درواره را بهعنوان یک Span ثبت کنید و دادههای Provider را به مراحل داخلی مانند احراز هویت، Billing، RAG، Validation و Tool Calling متصل کنید.
مقالات مرتبط
- چگونه یک API هوش مصنوعی قابلاعتماد برای محیط عملیاتی بسازیم؟
- Context Engineering چیست؟ آموزش مهندسی زمینه برای مدلها و Agentهای هوش مصنوعی
- Structured Outputs چیست؟ آموزش دریافت خروجی JSON از مدلهای هوش مصنوعی
- AI Router چیست؟ انتخاب خودکار مدل در اپلیکیشنهای هوش مصنوعی
- Token چیست و چگونه هزینه API هوش مصنوعی محاسبه میشود؟
- چگونه هزینه API هوش مصنوعی را کاهش دهیم؟
- Prompt Caching چیست؟
- RAG چیست؟ آموزش Retrieval-Augmented Generation
- Chunking چیست؟ آموزش تقسیم اسناد برای RAG
- Tool Calling و Function Calling چیست؟
- AI Agent چیست و چگونه کار میکند؟