Агуулгыг алгасах

AI pipeline (Gemini)

SDK-гүй REST урсгал: чат, дуу хоолой, шууд орчуулга — серверийн талд ажиллах хэрэгслүүдтэй (function calling).

Ерөнхий зураг

Хөтөч (/me/ai, /me/translate)
   │  ижил-origin fetch (CSRF толгойтой)
Next.js BFF  /api/ai/{chat,stt,tts,translate}   ← хэлбэрийг шалгаж JWT хавсаргана
   │  server→server
Go API  /api/v1/ai/*   (JWT + хязгаар ~20/мин)
usecases/ai ──────────► pkg/gemini ──────► Gemini REST API
   │   ▲                 (429/5xx/сүлжээнд 3× backoff retry)
   │   └─ functionResponse
ToolDef.Execute()  ← BACKEND дээр, хүсэлтийн контексттэй ажиллана
   ├─ search_knowledge → ai_knowledge хүснэгт
   └─ get_server_time  → жишээ хэрэгсэл

Гол зарчим

Загвар нь аль хэрэгслийг дуудахыг шийднэ; backend нь түүнийг гүйцэтгэнэ. Загвар код ажиллуулдаггүй. Хэрэгслүүд хүсэлтийн контексттэй ажилладаг тул тэдгээрийн хүрэх бүх өгөгдөлд RLS болон timeout нэгэн адил үйлчилнэ.

Чатын урсгал (function-calling давталт)

  1. Түүх (≤ 20 ээлж) дээр шинэ prompt нэмж contents угсарна. Дуут мессеж нь base64 inline audio хэсгээр ирнэ — Gemini үүнийг шууд ойлгодог тул тусад нь STT алхам хэрэггүй.
  2. Давхаргат system instruction + хэрэгслийн тодорхойлолттой хамт Gemini рүү дуудна.
  3. Хариунд function call байвал: хэрэгсэл бүрийг гүйцэтгэж, загварын ээлж + functionResponse ээлжийг нэмээд давтана (дээд тал нь MaxSteps, default 4). Гүйцэтгэсэн дуудалт бүрийг Step{Tool, Args, Result} болгон клиент рүү буцаадаг тул UI нь «AI юу хийсэн»-ийг харуулж чадна.
  4. Хариу текст бол шууд буцаана.

Алдааны семантик

Тохиолдол Үр дүн
Gemini түр зуурын алдаа (клиентийн 3× retry-ийн дараа) 5xx БИШ — хэрэглэгчийн хэл дээрх нөөц хариу, degraded: true
GEMINI_API_KEY байхгүй Жинхэнэ алдаа — 500, шалтгааныг лог руу
Хэрэгсэл унасан / танихгүй Загварт {"error": …} гэж мэдэгдэнэ — клиент рүү шууд гарахгүй

Энэ зан төлөвийг бүү өөрчил

Чат нь түр зуурын Gemini алдаанд нөөц хариу руу «зөөлөн» уналттай байх ёстой — үүнийг 5xx болгож хувиргаж болохгүй.

Prompt-ийн давхаргууд

System prompt нь хүсэлт бүрд гурван давхаргаас угсрагдана:

  1. Кодод хатуу бичсэн хамгаалалтын дүрэм (guardrails) — өөрчлөгддөггүй.
  2. Хамрах хүрээ (scope)ai_prompts хүснэгтээс, админ засварладаг.
  3. Заавар (instructions) — мөн DB-ээс тохируулагдана.

Хариултын хэл

Frontend нь UI-ийн хэлээ (mn/en/zh/ru) lang талбараар илгээх ба туслах ЗӨВХӨН тэр хэлээр хариулна — хэрэглэгчийн бичсэн хэл, ярианы түүх, мэдлэгийн сан, tool-ийн үр дүн үүнийг өөрчлөхгүй (өөр хэлтэй эх сурвалжийг орчуулж өгнө). degraded нөөц хариу ч мөн тэр хэлээр ирнэ.

Guardrail давхаргыг хэзээ ч тохируулга болгож болохгүй

Хамгаалалтын давхарга нь зөвхөн кодод байх ёстой. Зөвхөн scope ба instructions нь өгөгдлийн сангаас удирдагдана.

Хэрэгсэл нэмэх

ai.ToolDef{
    Declaration: gemini.FunctionDeclaration{
        Name:        "my_tool",
        Description: "Загвар үүнийг хэзээ дуудах ёстойг тайлбарла…",
        Parameters:  map[string]any{ /* JSON Schema */ },
    },
    Execute: func(ctx context.Context, args map[string]any) (map[string]any, error) {
        // backend дээр ажиллана; ctx нь хүсэлтийн identity-г авч явна (RLS үйлчилнэ)
        return map[string]any{"result": "…"}, nil
    },
}

cmd/api/server/server.go-д бүртгэнэ:

aiTools := append(ai.DefaultTools(), ai.KnowledgeSearchTool(aiRepo), myTool)

Бэлэн ирдэг хэрэгслүүд

Семантик хайлт (RAG)

Платформын мэдлэг ai_knowledge-д ~58 бүлгээр хадгалагдана. Асуултыг Gemini-ээр вектор болгож pgvector дээр cosine ойролцооллоор хайдаг тул өөр үг хэллэгээр асуусан ч зөв бүлэг олдоно. Embedding нь ачаалалтын дараа автоматаар гүйцээгдэнэ; Админ → Тохиргоо дотор гараар дахин индексжүүлэх товч бий.

  • search_knowledgeai_knowledge дээрх семантик хайлт: асуултыг embed хийж pgvector-ийн cosine зайгаар top-8-ыг аваад, шилдэг таарцтай харьцуулж шүүнэ (шилдгээс 0.03-оос хол зөрсөнг хаяна, 2–4 бичлэг). Тогтмол босго ажиллахгүй — энэ корпус дээр хамааралгүй хоёр бүлэг хүртэл 0.64+ ижилсэлтэй. Вектор боломжгүй үед ILIKE руу уналт хийж, асуултыг үг болгон задлаад урт үгсийн үндсээр хайна. Суурь guardrail нь платформын тухай асуултад хариулахын өмнө үүнийг дуудаж, олдоогүй бол таамаглахын оронд «мэдэхгүй» гэж хэлэхийг шаарддаг. Мэдлэгийн санг мөр нэмж өсгөнө — шинэ мөр автоматаар embed хийгдэнэ.
  • get_server_time — хамгийн жижиг жишээ (Улаанбаатарын цаг).

Нүүрийн нээлттэй чат (нэвтрэлтгүй)

Landing-ийн баруун доод буланд хөвөгч чат виджет байна — POST /public/ai/chat (токенгүй). Тусдаа usecase instance-аар зөвхөн мэдлэгийн сангийн tool-той холбогдсон тул хэрэглэгчийн өгөгдөлд хүрэхгүй. IP тус бүрт ~6/мин, мессеж ≤ 1000 тэмдэгт, түүх ≤ 6 ээлж; system prompt дээр «зочин» гэсэн нэмэлт хориг нэмэгдэнэ. Виджет POST /public/ai/chat/stream (SSE) хэрэглэдэг тул хариулт бичигдэж байхад нь харагдана. Push-to-talk (том дугуй товчийг дарж барих) нь ~250 KB base64 (≈ 15 сек) бичлэгийг явуулах ба model НЭГ дуудалтаар хуулбар (transcript event) ба хариултыг өгнө. Дуугаар асуувал хариултыг өгүүлбэр тус бүрээр нь POST /public/ai/tts-ээр шууд дуугаргана.

Дуу хоолой

Чадвар Endpoint Хэрхэн ажилладаг
Дуут чат мессеж POST /ai/chat (audio-тай) Аудио нь хэрэглэгчийн ээлжид inline data болж шууд орно — чат загвар мультимодаль
Яриа→текст (STT) POST /ai/stt «Үг үсгээр нь буулга» гэсэн хатуу зааврын нэг удаагийн дуудалт; хоосон текст = яриа алга
Текст→яриа (TTS) POST /ai/tts Тусдаа TTS загвар, responseModalities: ["AUDIO"]; түүхий PCM (L16/24kHz)-ийг WAV толгойд боож хөтөч тоглуулна
Шууд орчуулга POST /ai/translate Текст → орчуулга; аудио → хоёр алхам STT→орчуулга; speak: true бол TTS нэмнэ (TTS уналт чимээгүй — текст буцсан хэвээр)

Аудио оролт нь mime-ээр шүүгдэж (webm/ogg/wav/mpeg/mp3/mp4/m4a/aac/flac), BFF болон backend DTO хоёуланд ~700 KB base64 (~30 сек opus)-аар хязгаарлагдана.

Шууд орчуулгын онцлог

Микрофон ~7 секундын хэсгүүдээр бичдэг ба хэсэг бүрт шинэ MediaRecorder үүсгэдэг — timeslice хэсгүүдийн зөвхөн эхнийх нь контейнерийн толгойг авч явдаг тул ингэж хийж байж хэсэг бүр бие даан хүчинтэй болно. Чимээгүй хэсэг хоосон талбар буцаадаг ба алдаа гэж үзэлгүй хаягдана.

Хязгаарлалт

/ai/* нь IP тус бүрд ~20 хүсэлт/минут. Шууд орчуулга минутад ~8 хэсэг дамжуулдаг тул энэ хязгаарыг багасгахдаа болгоомжтой.

Дэлгэрэнгүй: репозиторын backend/docs/AI_PIPELINE_MN.md.