234 lines
7.2 KiB
YAML
234 lines
7.2 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: LCBP3 RAG API
|
|
description: Retrieval-Augmented Generation endpoints for LCBP3 DMS (ADR-022)
|
|
version: 1.0.0
|
|
|
|
servers:
|
|
- url: /api
|
|
|
|
security:
|
|
- bearerAuth: []
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
|
|
schemas:
|
|
RagQueryRequest:
|
|
type: object
|
|
required: [ question, projectPublicId ]
|
|
properties:
|
|
question:
|
|
type: string
|
|
maxLength: 500
|
|
description: คำถามภาษาไทย/อังกฤษ
|
|
example: "เอกสาร REF-2026-001 มีเนื้อหาอะไร?"
|
|
projectPublicId:
|
|
type: string
|
|
format: uuid
|
|
description: UUIDv7 ของโครงการ (mandatory tenant isolation)
|
|
maxClassification:
|
|
type: string
|
|
enum: [ PUBLIC, INTERNAL, CONFIDENTIAL ]
|
|
default: INTERNAL
|
|
description: ระดับ classification สูงสุดที่ user มีสิทธิ์เข้าถึง
|
|
|
|
Citation:
|
|
type: object
|
|
properties:
|
|
chunkId:
|
|
type: string
|
|
format: uuid
|
|
docNumber:
|
|
type: string
|
|
nullable: true
|
|
example: "REF-2026-001"
|
|
docType:
|
|
type: string
|
|
example: "CORR"
|
|
revision:
|
|
type: string
|
|
nullable: true
|
|
example: "Rev.A"
|
|
snippet:
|
|
type: string
|
|
description: ข้อความส่วนที่ตอบคำถาม (max 200 chars)
|
|
score:
|
|
type: number
|
|
format: float
|
|
minimum: 0
|
|
maximum: 1
|
|
|
|
RagQueryResponse:
|
|
type: object
|
|
properties:
|
|
answer:
|
|
type: string
|
|
description: คำตอบที่ AI สร้างขึ้นจาก context
|
|
citations:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Citation"
|
|
confidence:
|
|
type: number
|
|
format: float
|
|
minimum: 0
|
|
maximum: 1
|
|
description: ระดับความมั่นใจของคำตอบ (< 0.6 = fallback message)
|
|
fallbackUsed:
|
|
type: boolean
|
|
description: true = ใช้ Ollama local LLM แทน Typhoon API
|
|
latencyMs:
|
|
type: integer
|
|
description: เวลา end-to-end (ms)
|
|
|
|
RagIngestionStatus:
|
|
type: object
|
|
properties:
|
|
attachmentId:
|
|
type: string
|
|
format: uuid
|
|
ragStatus:
|
|
type: string
|
|
enum: [ PENDING, PROCESSING, INDEXED, FAILED ]
|
|
ragLastError:
|
|
type: string
|
|
nullable: true
|
|
chunkCount:
|
|
type: integer
|
|
description: จำนวน chunks ที่ indexed แล้ว (0 ถ้ายังไม่ INDEXED)
|
|
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
statusCode:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
userMessage:
|
|
type: string
|
|
description: ข้อความที่แสดงต่อ user (ภาษาไทย)
|
|
recoveryAction:
|
|
type: string
|
|
nullable: true
|
|
|
|
paths:
|
|
/rag/query:
|
|
post:
|
|
summary: RAG Query — ถามคำถามจากเอกสารโครงการ
|
|
description: |
|
|
ค้นหา context จากเอกสารที่ indexed แล้วและสร้างคำตอบด้วย AI
|
|
- CONFIDENTIAL documents → ใช้ local Ollama เท่านั้น (ADR-018)
|
|
- ทุก query บังคับระบุ projectPublicId เพื่อ tenant isolation
|
|
- Idempotency-Key header บังคับ (AGENTS.md security rule)
|
|
tags: [ RAG ]
|
|
parameters:
|
|
- name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
description: UUIDv4 idempotency key — prevent duplicate query submissions
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/RagQueryRequest"
|
|
responses:
|
|
"200":
|
|
description: คำตอบพร้อม citations
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
$ref: "#/components/schemas/RagQueryResponse"
|
|
"400":
|
|
description: Invalid input (question เปล่า หรือ projectPublicId ไม่ถูกต้อง)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"403":
|
|
description: ไม่มีสิทธิ์เข้าถึงโครงการนี้
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ErrorResponse"
|
|
"429":
|
|
description: Rate limit exceeded
|
|
"503":
|
|
description: RAG service unavailable (Qdrant / Ollama / Typhoon ทั้งหมด down)
|
|
|
|
/rag/status/{attachmentId}:
|
|
get:
|
|
summary: ตรวจสอบสถานะ RAG ingestion ของ attachment
|
|
tags: [ RAG ]
|
|
parameters:
|
|
- name: attachmentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
description: publicId (UUIDv7) ของ attachment
|
|
responses:
|
|
"200":
|
|
description: สถานะ ingestion ปัจจุบัน
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
$ref: "#/components/schemas/RagIngestionStatus"
|
|
"404":
|
|
description: Attachment ไม่พบ
|
|
|
|
/rag/ingest/{attachmentId}:
|
|
post:
|
|
summary: Trigger manual re-ingestion (สำหรับไฟล์ที่ FAILED)
|
|
description: Re-enqueue rag:ocr job สำหรับ attachment; reset rag_status → PENDING
|
|
tags: [ RAG ]
|
|
parameters:
|
|
- name: attachmentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
"202":
|
|
description: Re-ingestion job queued
|
|
"400":
|
|
description: Attachment ไม่อยู่ใน FAILED state
|
|
"404":
|
|
description: Attachment ไม่พบ
|
|
|
|
/rag/vectors/{attachmentId}:
|
|
delete:
|
|
summary: ลบ vectors ของ attachment จาก Qdrant (เมื่อลบเอกสาร)
|
|
description: |
|
|
เรียกโดย DocumentService เมื่อ soft-delete attachment
|
|
ลบ Qdrant points + document_chunks rows ทั้งหมดของ attachment
|
|
tags: [ RAG ]
|
|
parameters:
|
|
- name: attachmentId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
"200":
|
|
description: Vectors deleted successfully
|
|
"404":
|
|
description: Attachment ไม่พบ
|