openapi: 3.0.3 info: title: Intent Classification API description: API สำหรับ Intent Classification ตาม ADR-024 (Hybrid Pattern First → LLM Fallback) version: 1.0.0 contact: name: NAP-DMS Development Team servers: - url: http://localhost:3001/api description: Local Development - url: https://api.nap-dms.work/api description: Production tags: - name: Intent Classification description: แปลงคำถามธรรมชาติ → Server-side Intent - name: Intent Management description: Admin API สำหรับจัดการ Intent Definitions และ Patterns paths: # === Intent Classification === /ai/intent/classify: post: summary: Classify User Query description: | แปลงคำถามธรรมชาติจาก User เป็น Server-side Intent enum ใช้ Hybrid Strategy: Pattern First → LLM Fallback tags: [Intent Classification] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ClassifyQueryRequest' example: query: "สรุปเอกสารนี้" projectPublicId: "019505a1-7c3e-7000-8000-abc123def456" responses: '200': description: Classification successful content: application/json: schema: $ref: '#/components/schemas/ClassificationResult' examples: pattern-match: summary: Pattern Match (cache hit) value: intentCode: "SUMMARIZE_DOCUMENT" confidence: 1.0 method: "pattern" latencyMs: 8 llm-fallback: summary: LLM Fallback value: intentCode: "GET_RFA" confidence: 0.85 method: "llm_fallback" params: contractPublicId: "019505a1-7c3e-7000-8000-xyz789abc123" latencyMs: 1250 fallback: summary: No Match (FALLBACK) value: intentCode: "FALLBACK" confidence: 0.0 method: "llm_fallback" latencyMs: 2100 '400': description: Invalid request (missing query) '401': description: Unauthorized '429': description: Too many requests (rate limit) # === Intent Definitions (Admin) === /admin/ai/intent-definitions: get: summary: List Intent Definitions description: ดึงรายการ Intent Definitions ทั้งหมด tags: [Intent Management] security: - bearerAuth: [] parameters: - name: category in: query schema: type: string enum: [read, suggest, utility] description: Filter by category - name: isActive in: query schema: type: boolean description: Filter by active status responses: '200': description: List of intent definitions content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/IntentDefinition' post: summary: Create Intent Definition description: สร้าง Intent Definition ใหม่ (System Admin only) tags: [Intent Management] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateIntentDefinitionRequest' responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/IntentDefinition' '409': description: Intent code already exists /admin/ai/intent-definitions/{intentCode}: parameters: - name: intentCode in: path required: true schema: type: string example: "GET_RFA" get: summary: Get Intent Definition tags: [Intent Management] security: - bearerAuth: [] responses: '200': description: Intent definition found content: application/json: schema: $ref: '#/components/schemas/IntentDefinition' '404': description: Intent not found patch: summary: Update Intent Definition tags: [Intent Management] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateIntentDefinitionRequest' responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/IntentDefinition' # === Intent Patterns (Admin) === /admin/ai/intent-definitions/{intentCode}/patterns: parameters: - name: intentCode in: path required: true schema: type: string get: summary: List Patterns for Intent tags: [Intent Management] security: - bearerAuth: [] responses: '200': description: List of patterns content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/IntentPattern' post: summary: Create Pattern for Intent description: เพิ่ม Pattern ใหม่สำหรับ Intent นี้ tags: [Intent Management] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateIntentPatternRequest' responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/IntentPattern' '400': description: Invalid regex pattern /admin/ai/intent-patterns/{publicId}: parameters: - name: publicId in: path required: true schema: type: string format: uuid get: summary: Get Pattern tags: [Intent Management] security: - bearerAuth: [] responses: '200': description: Pattern found content: application/json: schema: $ref: '#/components/schemas/IntentPattern' patch: summary: Update Pattern tags: [Intent Management] security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateIntentPatternRequest' responses: '200': description: Updated delete: summary: Delete Pattern (soft delete) tags: [Intent Management] security: - bearerAuth: [] responses: '204': description: Deleted components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: # === Classification === ClassifyQueryRequest: type: object required: [query] properties: query: type: string maxLength: 200 description: คำถามจาก user (trim แล้ว) example: "สรุปเอกสารนี้" projectPublicId: type: string format: uuid description: Context project userPublicId: type: string format: uuid description: Context user currentDocumentId: type: string format: uuid description: Document ที่เปิดอยู่ (ถ้ามี) ClassificationResult: type: object properties: intentCode: type: string description: Intent ที่จำแนกได้ example: "SUMMARIZE_DOCUMENT" confidence: type: number minimum: 0 maximum: 1 description: ความมั่นใจ (1.0 = pattern match) example: 1.0 method: type: string enum: [pattern, llm_fallback, semaphore_overflow, llm_error] description: วิธีที่ใช้จำแนก params: type: object additionalProperties: true description: Parameters ที่สกัดได้ (optional) latencyMs: type: integer description: เวลาที่ใช้ทั้งหมด (ms) example: 8 # === Intent Definition === IntentDefinition: type: object properties: publicId: type: string format: uuid intentCode: type: string example: "GET_RFA" descriptionTh: type: string example: "ดึง RFA ตาม filter" descriptionEn: type: string example: "Get RFA by filters" category: type: string enum: [read, suggest, utility] isActive: type: boolean createdAt: type: string format: date-time updatedAt: type: string format: date-time CreateIntentDefinitionRequest: type: object required: [intentCode, descriptionTh, descriptionEn, category] properties: intentCode: type: string pattern: '^[A-Z][A-Z0-9_]*$' example: "GET_CONTRACT" descriptionTh: type: string maxLength: 255 descriptionEn: type: string maxLength: 255 category: type: string enum: [read, suggest, utility] UpdateIntentDefinitionRequest: type: object properties: descriptionTh: type: string maxLength: 255 descriptionEn: type: string maxLength: 255 isActive: type: boolean # === Intent Pattern === IntentPattern: type: object properties: publicId: type: string format: uuid intentCode: type: string language: type: string enum: [th, en, any] patternType: type: string enum: [keyword, regex] patternValue: type: string maxLength: 255 priority: type: integer description: ลำดับการตรวจสอบ (ต่ำ = ตรวจก่อน) isActive: type: boolean createdAt: type: string format: date-time updatedAt: type: string format: date-time CreateIntentPatternRequest: type: object required: [patternType, patternValue] properties: language: type: string enum: [th, en, any] default: any patternType: type: string enum: [keyword, regex] patternValue: type: string maxLength: 255 priority: type: integer default: 100 UpdateIntentPatternRequest: type: object properties: language: type: string enum: [th, en, any] patternType: type: string enum: [keyword, regex] patternValue: type: string maxLength: 255 priority: type: integer isActive: type: boolean