راهنماها
اتصال به سیستم تیکت
این یک نمونه برای اتصال مهوش به سیستم تیکتی است که همین حالا استفاده میکنید. وقتی مشتری پیامی میفرستد، مهوش پیام را بررسی میکند، تیکت را دستهبندی میکند و اگر جواب در اسناد راهنمای شما باشد، یک پیشنویس پاسخ همراه با منبع مینویسد. هر پیشنویس پیش از رسیدن به مشتری، توسط کارشناس بازبینی میشود.
بخشهای این سناریو چطور به هم وصلاند
- 01بررسی پیام
- 02دستهبندی
- 03پیشنویس پاسخ
- 04بازبینی کارشناس
روند کار
مراحل ۱ تا ۴ را یک بار در اپلیکیشن مهوش انجام میدهید. مراحل ۵ تا ۸ برای هر پیام مشتری، در یک کار پسزمینه روی سرور سیستم تیکت شما اجرا میشوند. تیکتها، مشتریان و ارسال پاسخ در سیستم خود شما میمانند و مهوش هیچوقت مستقیم با مشتری شما تماس نمیگیرد.
| مرحله | چه اتفاقی میافتد | چه وقت تیکت بدون پیشنویس به کارشناس میرسد |
|---|---|---|
| ۵. بررسی پیام | مهوش پیام مشتری را از نظر محتوای آسیبزا مثل آزار، تهدید یا آسیب به خود بررسی میکند. | پیام علامت خورده باشد. |
| ۶. دستهبندی | مهوش تیکت را برچسب میزند: موضوع، اینکه اسناد شما جوابش را دارند یا نه، ریسکها، اولویت و اینکه پیام را انسان نوشته یا نه. تصمیم با کد شماست. | تیکت ریسک دارد، به اطلاعات حساب یا تأیید یک انسان نیاز دارد، یا خارج از حوزهٔ کار شماست. پیامهای خودکار نادیده گرفته میشوند. |
| ۷. پیشنویس | مهوش در اسناد راهنمای شما جستوجو میکند و پاسخی همراه با فایلهایی که استفاده کرده مینویسد. | اسناد جواب پرسش را ندارند یا پاسخ به هیچ فایلی ارجاع نمیدهد. |
| ۸. بازبینی | کارشناس پیشنویس را میخواند، ویرایش میکند و میفرستد یا رد میکند. | هیچ چیزی بدون کارشناس به مشتری نمیرسد. |
همهٔ requestها و responseهای این صفحه روی یک پروژهٔ واقعی مهوش اجرا شدهاند. responseها کوتاه شدهاند و شناسهها با جانگهدار جایگزین شدهاند.
۱. ساخت پروژه
مراحل ۱ تا ۴ در اپلیکیشن مهوش انجام میشوند؛ همان جایی که با مهوش گفتوگو میکنید. به پنل مدیریت نیازی ندارید.
- ۱وارد اپلیکیشن مهوش شوید. در نوار کناری، کنار پروژهها روی پروژه جدید بزنید، یک نام بگذارید (مثلاً
پشتیبانی تیکتها) و پروژه را بسازید. - ۲پروژه را باز کنید، به زبانهٔ دستورالعملها بروید، متن زیر را وارد کنید، بهجای
[نام شرکت شما]نام شرکتتان را بنویسید و روی ذخیره دستورالعملها بزنید. - ۳شناسهٔ پروژه را کپی کنید. وقتی پروژه باز است، این شناسه بخش آخر نشانی صفحه در مرورگر است:
.../chat/projects/<شناسهٔ پروژه>. از API هم میتوانید آن را بگیرید:GET /api/v1/tenancy/projectsپروژههای شما را همراه باidفهرست میکند.
تو دستیار پشتیبانی [نام شرکت شما] هستی و به کارشناسهای پشتیبانی در پاسخ به تیکت مشتریها کمک میکنی.
- فقط بر اساس اسناد متصل به این پروژه پاسخ بده. قیمت، تاریخ، مهلت یا قانونی از خودت نساز.
- هرگز بازگشت وجه، جبران خسارت، استثنا یا نتیجهٔ حقوقی را قول نده. این تصمیمها با انسان است.
- هرگز رمز عبور، شمارهٔ کامل کارت یا کد تأیید را از مشتری نخواه.
- به زبان خود مشتری، مؤدبانه، روشن و کوتاه پاسخ بده.دستورالعمل پروژه روی همهٔ requestهایی که با کلید این پروژه فرستاده میشوند اعمال میشود؛ پس فقط قانونهایی را در آن بنویسید که همیشه برقرارند. متن مخصوص هر کار در پرامپتهای مرحلهٔ ۳ میآید.
نکته:پروژهای که در اپلیکیشن ساخته میشود بهطور خودکار در منابعش جستوجو میکند؛ پس request پیشنویس، بدون نام بردن از اسناد، آنها را پیدا میکند.
نکته:همهٔ requestهای مراحل ۵ تا ۷ این شناسه را در هدر X-Mahvash-Project میفرستند. پرامپتهایی که در مرحلهٔ ۳ میسازید متعلق به همین پروژهاند و مهوش آنها را در همین پروژه پیدا میکند؛ requestی که پروژهٔ دیگری را نام ببرد رد میشود.
APIهای این مرحله
۲. افزودن اسناد راهنما
- ۱در پروژه، زبانهٔ منابع را باز کنید و روی افزودن منبع بزنید. فایلها را یکییکی اضافه کنید.
- ۲اسنادی را بارگذاری کنید که پاسخها باید از آنها بیایند: مقالههای مرکز راهنما، قوانین مرجوعی و ارسال، صفحههای طرح و قیمت، پرسشهای متداول. فایلهای PDF، Word، متنی، Markdown، CSV و صفحهگسترده پشتیبانی میشوند.
- ۳صبر کنید تا وضعیت همهٔ فایلها آماده شود. تا وقتی پردازش ادامه دارد، با بهروزرسانی فهرست را تازه کنید. پیشنویسها فقط از فایلهای آماده استفاده میکنند.
وقتی قانونی تغییر میکند، فایل جدید را اضافه و فایل قدیمی را با دکمهٔ حذف کنارش پاک کنید تا پیشنویسها قانون منسوخ را نقل نکنند.
مهم:هر چیزی که بارگذاری کنید ممکن است در پاسخ به مشتری بیاید. یادداشتهای داخلی، اطلاعات مشتریان یا هر چیزی را که نمیخواهید به مشتری برسد، بارگذاری نکنید.
۳. افزودن دو پرامپت
زبانهٔ پرامپتها را در پروژه باز کنید، روی اضافه کردن پرامپت جدید بزنید و دو پرامپت زیر را بسازید: نام را بنویسید، متن را وارد کنید و ذخیره کنید. شناسهٔ هر پرامپت در فهرست، همراه با دکمهٔ کپی کنارش نمایش داده میشود؛ کد شما این شناسه را با هر request میفرستد.
پرامپت دستهبندی
نام: ticket-triage. متن:
تیکت پشتیبانی ورودی را دستهبندی کن. به آن پاسخ نده.
category: نزدیکترین موضوع از میان مقدارهای مجاز. اگر هیچکدام مناسب نیست، "other".
answerability:
- "kb_answerable": پرسشی عمومی که اسناد راهنمای ما جوابش را دارند؛ مثل نحوهٔ استفاده، قوانین، زمان ارسال یا طرحها.
- "needs_account_data": جواب به سفارش، پرداخت یا حساب خود همین مشتری بستگی دارد.
- "needs_human_authority": مشتری بازگشت وجه، جبران خسارت، استثنا، حذف حساب یا هر چیزی را میخواهد که باید یک انسان تأییدش کند.
- "out_of_scope": ربطی به محصولات یا خدمات ما ندارد.
risk_flags: همهٔ برچسبهایی که صدق میکنند، یا فهرست خالی.
- "legal": تهدید به شکایت، وکیل یا گزارش به مراجع.
- "chargeback": اشاره به اعتراض بانکی یا برگشت تراکنش.
- "security": حساب هکشده، نشت اطلاعات یا ورود مشکوک.
- "self_harm": هر نشانهای از اینکه فرد ممکن است به خودش آسیب بزند.
- "abuse": توهین یا تهدید علیه کارکنان.
- "churn": میگوید سرویس را لغو میکند یا سراغ رقیب میرود.
priority: "urgent" وقتی سرویس برایش کاملاً از کار افتاده یا پولی به اشتباه کسر شده؛ "high" وقتی کارش متوقف شده؛ در غیر این صورت "normal" یا "low".
is_automated_sender: برای پاسخ خودکار «خارج از دفتر»، اعلانهای سیستمی و هر پیامی که انسان ننوشته، true.
language: کد ISO 639-1 زبان مشتری؛ مثلاً "fa" یا "en".
reason: یک جملهٔ کوتاه که دلیل category و answerability را توضیح دهد.پرامپت پاسخ
نام: ticket-reply. متن:
به تیکت مشتری در ورودی پاسخ بنویس. یک کارشناس پشتیبانی آن را بازبینی میکند و همانطور که هست برای مشتری میفرستد.
- در اسناد پروژه جستوجو کن و فقط از چیزی استفاده کن که در آنها آمده است.
- اگر اسناد جواب پرسش را ندارند، status را "insufficient_information" بگذار، reply را رشتهٔ خالی بگذار و در internal_note بنویس چه اطلاعاتی کم است.
- فقط به همان چیزی که مشتری پرسیده جواب بده. پیشنهاد یا قول اضافه نده.
- reply متن سادهٔ مخصوص مشتری و به زبان خود اوست: بدون markdown، بدون نام فایل و بدون اشاره به اسناد، این دستورالعملها یا هوش مصنوعی.
- internal_note برای کارشناس است و هیچوقت خالی نمیماند: نام دقیق فایل همهٔ اسنادی را که پاسخ بر اساس آنها نوشته شده بیاور، سپس در یک جمله بگو کارشناس چه چیزی را باید بررسی کند.پرامپت فقط دستورالعمل را نگه میدارد. شکل دقیق JSON هر پاسخ همراه request فرستاده میشود (مراحل ۶ و ۷) و مهوش پاسخی را که با آن شکل نخواند رد میکند.
مهوش فقط وقتی سندی را بهعنوان منبع (file_citation) علامت میزند که پاسخ نام فایل آن را آورده باشد. به همین دلیل پرامپت پاسخ از مدل میخواهد منبعها را در internal_note بنویسد: کارشناس آنها را میبیند، مشتری نمیبیند، و ارجاع هم برمیگردد.
نکته:برای تغییر پرامپت، روی نامش در فهرست بزنید، ویرایشش کنید و ذخیره کنید. شناسه تغییر نمیکند؛ پس کد شما هم تغییری نمیخواهد.
APIهای این مرحله
۴. ساخت کلید API
- ۱در پروژه، زبانهٔ کلیدهای API را باز کنید و روی اضافه کردن کلید جدید بزنید. نام کلید را از روی سیستم تیکتتان بگذارید؛ مثلاً
helpdesk-worker. این زبانه فقط برای مالک و مدیران سازمان نمایش داده میشود. - ۲کلید را همان لحظه کپی کنید. فقط یک بار نمایش داده میشود.
- ۳کلید، شناسهٔ پروژه و دو شناسهٔ پرامپت را در متغیرهای محیطی سرور سیستم تیکت قرار دهید:
# Your ticketing server's environment. Never commit this file.
MAHVASH_API_URL=https://api.mahvashai.ir
MAHVASH_API_KEY=<the key from step 4>
MAHVASH_PROJECT_ID=<the project ID from step 1>
MAHVASH_TRIAGE_PROMPT_ID=<Prompt ID of ticket-triage>
MAHVASH_REPLY_PROMPT_ID=<Prompt ID of ticket-reply>هر requestی که با این کلید فرستاده شود از دستورالعمل، منابع و سقفهای همین پروژه استفاده میکند و هزینهاش از حساب سازمان شما کسر میشود.
مهم:کلید را فقط روی سرور نگه دارید. هرگز آن را در frontend سیستم تیکت نگذارید یا به مرورگر نفرستید. اگر لو رفت، در همان زبانه لغوش کنید و کلید جدید بسازید.
APIهای این مرحله
۵. بررسی پیام مشتری
وقتی پیام مشتری ذخیره میشود، کد شما اول متن آن را برای moderation میفرستد. moderation محتوای آسیبزا مثل آزار، تهدید یا آسیب به خود را پیدا میکند. تصمیم نمیگیرد که تیکت قابل پاسخ است یا نه؛ آن کار دستهبندی است.
curl "$MAHVASH_API_URL/v1/moderations" -H "Authorization: Bearer $MAHVASH_API_KEY" -H "X-Mahvash-Project: $MAHVASH_PROJECT_ID" -H "Content-Type: application/json" -d @- <<EOF
{
"model": "omni-moderation-latest",
"input": [
"سلام، لباسشویی دیروز با در شکسته به دستم رسید. میتوانم مرجوعش کنم یا باید از گارانتی استفاده کنم؟"
]
}
EOFاگر results[0].flagged برابر true بود، همینجا متوقف شوید و تیکت را بدون پیشنویس به کارشناس بسپارید.
APIهای این مرحله
۶. دستهبندی: هوش مصنوعی جواب بدهد یا نه؟
در این مرحله از مدل میخواهید تیکت را برچسب بزند، نه اینکه جوابش را بدهد. برچسبها بهصورت JSON با شکل ثابت برمیگردند؛ پس کد شما بهجای تجزیهٔ جملهها، فیلدها را میخواند.
curl "$MAHVASH_API_URL/v1/responses" -H "Authorization: Bearer $MAHVASH_API_KEY" -H "X-Mahvash-Project: $MAHVASH_PROJECT_ID" -H "Content-Type: application/json" -d @- <<EOF
{
"model": "gpt-6-luna",
"prompt_id": "$MAHVASH_TRIAGE_PROMPT_ID",
"input": "سلام، لباسشویی دیروز با در شکسته به دستم رسید. میتوانم مرجوعش کنم یا باید از گارانتی استفاده کنم؟",
"text": {
"format": {
"type": "json_schema",
"name": "ticket_triage",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"category",
"answerability",
"risk_flags",
"priority",
"is_automated_sender",
"language",
"reason"
],
"properties": {
"category": {
"type": "string",
"enum": [
"order_delivery",
"returns_refunds",
"billing",
"account_access",
"how_to",
"technical_issue",
"other"
]
},
"answerability": {
"type": "string",
"enum": [
"kb_answerable",
"needs_account_data",
"needs_human_authority",
"out_of_scope"
]
},
"risk_flags": {
"type": "array",
"items": {
"type": "string",
"enum": [
"legal",
"chargeback",
"security",
"self_harm",
"abuse",
"churn"
]
}
},
"priority": {
"type": "string",
"enum": [
"low",
"normal",
"high",
"urgent"
]
},
"is_automated_sender": {
"type": "boolean"
},
"language": {
"type": "string"
},
"reason": {
"type": "string"
}
}
}
}
}
}
EOFtext آیتم message در output را بردارید و بهصورت JSON بخوانید؛ زبانهٔ Result همین را نشان میدهد. جدول زیر همهٔ فیلدهایی را که برمیگردد و کاری را که کد شما با هر کدام میکند نشان میدهد. به فیلدها تکیه کنید، نه به متن: reason متن آزاد برای انسان است و language ممکن است بهجای کد، نام زبان باشد؛ مثلاً Persian.
| فیلد | مقدارها | کاری که کد شما میکند |
|---|---|---|
category | دستههای خودتان در schema؛ مثلاً returns_refunds | تیکت را به صف مناسب میفرستد. پیشنویس را فقط برای دستههایی فعال کنید که آزمودهاید. |
answerability | kb_answerable، needs_account_data، needs_human_authority، out_of_scope | فقط kb_answerable به مرحلهٔ پیشنویس میرود. هر مقدار دیگری به کارشناس سپرده میشود. |
risk_flags | فهرستی از legal، chargeback، security، self_harm، abuse، churn یا خالی | هر برچسبی تیکت را فوراً و بدون پیشنویس به کارشناس میسپارد. |
priority | low، normal، high، urgent | اولویت تیکت را در سیستم شما تعیین میکند؛ دربارهٔ نوشتن پیشنویس تصمیم نمیگیرد. |
is_automated_sender | true یا false | true یعنی پاسخ خودکار یا پیام سیستمی: نادیده بگیرید و هرگز جوابش را ندهید. |
language | کد یا نام زبان | تیم کارشناس یا زبان قالبهای پاسخ را انتخاب میکند. |
reason | متن آزاد | به کارشناس نشان دهید. هیچ تصمیمی را بر اساس آن نگیرید. |
تصمیم با کد شماست
def decide(triage: dict) -> str:
"""Return "ignore", "agent" or "draft". These are your rules, not the model's."""
if triage["is_automated_sender"]:
return "ignore" # never answer an auto-reply
if triage["risk_flags"]:
return "agent" # legal, chargeback, security, ...: always a person
if triage["answerability"] != "kb_answerable":
return "agent" # needs account data or someone's approval
return "draft"APIهای این مرحله
۷. نوشتن پیشنویس پاسخ
برای تیکتی که از دستهبندی رد شده، گفتوگو را برای پرامپت پاسخ بفرستید. چون پروژه بهطور خودکار در منابعش جستوجو میکند، مهوش پیش از نوشتن در اسناد شما جستوجو میکند. input گفتوگوی عمومی تیکت است، از قدیمی به جدید: پیامهای مشتری با نقش user و پاسخهای کارشناسهای شما با نقش assistant.
curl "$MAHVASH_API_URL/v1/responses" -H "Authorization: Bearer $MAHVASH_API_KEY" -H "X-Mahvash-Project: $MAHVASH_PROJECT_ID" -H "Content-Type: application/json" -d @- <<EOF
{
"model": "gpt-6-luna",
"prompt_id": "$MAHVASH_REPLY_PROMPT_ID",
"input": [
{
"role": "user",
"content": "سلام، لباسشویی دیروز با در شکسته به دستم رسید. میتوانم مرجوعش کنم یا باید از گارانتی استفاده کنم؟"
}
],
"text": {
"format": {
"type": "json_schema",
"name": "ticket_reply",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"reply",
"internal_note"
],
"properties": {
"status": {
"type": "string",
"enum": [
"answered",
"insufficient_information"
]
},
"reply": {
"type": "string"
},
"internal_note": {
"type": "string"
}
}
}
}
}
}
EOFدو وضعیت تعیین میکنند با پیشنویس چه کنید: status خود response و status داخل JSONی که مدل نوشته. به همین ترتیب بررسی کنید:
| چه میبینید | یعنی چه | چه کنید |
|---|---|---|
status خود response برابر failed یا incomplete است، یا کد HTTP برابر 200 نیست | پیشنویس قابل استفادهای ساخته نشده است. | تیکت را بدون پیشنویس به کارشناس بسپارید. |
status داخل JSON برابر insufficient_information است | اسناد جواب پرسش را ندارند و internal_note میگوید چه چیزی کم است. | تیکت را بدون پیشنویس به کارشناس بسپارید و یادداشت را به او نشان دهید. به status تکیه کنید، نه به خالی بودن reply. |
status داخل JSON برابر answered است اما در annotations هیچ file_citationی نیست | پاسخی بدون منبع اثباتشده. | تیکت را بدون پیشنویس به کارشناس بسپارید. |
status داخل JSON برابر answered است و دستکم یک file_citation وجود دارد | پیشنویسی متکی بر اسناد شما. | آن را همراه با منبعها و internal_note برای بازبینی کارشناس (مرحلهٔ ۸) ذخیره کنید. |
پیشنویس فقط در ردیف آخر قابل استفاده است. در نمونهٔ بالا مدل نام help-center.md را آورده، پس file_citation برگشته و پیشنویس نگه داشته میشود. اگر مدل جواب درستی بنویسد اما نام فایل منبع را نیاورد، file_citation برنمیگردد و تیکت بدون پیشنویس به کارشناس میرسد.
APIهای این مرحله
۸. بازبینی کارشناس
پیشنویس را داخل تیکت و بهصورت یادداشت خصوصی که فقط کارشناسها میبینند نمایش دهید، همراه با:
- متن پاسخ در یک کادر قابل ویرایش؛
- فایلهای منبع، با پیوند به صفحهٔ متناظر در مرکز راهنمای خودتان؛
internal_note؛- سه دکمه: ارسال، ویرایش و ارسال و رد کردن.
نکته:چون منبعها در internal_note میآیند، خود پاسخ تمیز میماند. اگر پاسخی باز هم نام فایلی را آورد، کارشناس پیش از ارسال آن را پاک میکند.
برای هر پیشنویس اینها را ذخیره کنید: شناسهٔ تیکت و پیام، شناسهٔ response مهوش، برچسبهای دستهبندی، پیشنویس، کاری که کارشناس انجام داد و متنی که واقعاً فرستاده شد. همین سابقه نشان میدهد پیشنویسها در کدام دستهها خوب کار میکنند.
قانونهای ایمنی
- تا کارشناس دکمهٔ ارسال را نزند، هیچ چیزی به مشتری نمیرسد.
- برای هر پیام مشتری فقط یک پیشنویس. هر پیام جدید مشتری یک پیشنویس جدید میگیرد.
- اگر کارشناسی شروع به نوشتن پاسخ کرده، متن او را با پیشنویس جایگزین نکنید.
ارسال بدون بازبینی
در شروع، همهٔ پیشنویسها را بازبینی کنید. بعد از چند هفته، برای هر دسته بررسی کنید کارشناسها چند بار پیشنویس را بدون تغییر فرستادهاند. فقط دستهای که در آن این اتفاق تقریباً همیشه میافتد، و فقط برای تیکتهایی با kb_answerable و بدون برچسب ریسک، برای ارسال بدون بازبینی مناسب است. حتی در آن حالت هم هر روز نمونهای از پاسخها را بازبینی کنید.