LuatVietnam AI Assistant API

LuatVietnam AI Assistant API - Integration Guide

Base URL: https://luatvietnam-api.lumination.vn
Auth: dùng header x-api-key
Content-Type: application/json, riêng upload file dùng multipart/form-data

1. Xác thực

Tất cả API trong tài liệu này đều yêu cầu header:

x-api-key: <API_KEY_DUOC_CAP>

Ngoài API key, hệ thống có kiểm soát whitelist IP. Đối tác tích hợp cần gửi danh sách IP public dùng để gọi API để được cấu hình whitelist trước khi go-live.

Nếu thiếu hoặc sai API key, hệ thống sẽ trả về:

{
  "detail": "Invalid API key"
}

Nếu IP chưa được whitelist, hệ thống sẽ trả về:

{
  "detail": "Client IP is not allowed"
}

2. Chat Assistant

2.1 Tạo cuộc hội thoại

POST /v1/conversations
Content-Type: application/json

Request body:

{
  "name": "Tư vấn thành lập công ty",
  "metadata": {
    "user_id": "user_123"
  }
}

Response:

{
  "name": "Tư vấn thành lập công ty",
  "metadata": {
    "user_id": "user_123"
  },
  "message_count": 0,
  "created_at": "2026-05-28T03:00:00.000Z",
  "updated_at": "2026-05-28T03:00:00.000Z",
  "deleted_at": null,
  "id": "6657f2d8a0f0f2a1a1111111"
}
Có thể bỏ qua bước tạo conversation. Khi gọi chat mà không truyền conversation_id, hệ thống sẽ tự tạo conversation mới.

2.2 Lấy danh sách cuộc hội thoại

GET /v1/conversations?page=1&page_size=20

Response:

{
  "items": [
    {
      "id": "6657f2d8a0f0f2a1a1111111",
      "name": "Tư vấn thành lập công ty",
      "message_count": 4,
      "created_at": "2026-05-28T03:00:00.000Z",
      "updated_at": "2026-05-28T03:10:00.000Z",
      "deleted_at": null,
      "metadata": {}
    }
  ],
  "page": 1,
  "page_size": 20,
  "total_count": 1,
  "total_pages": 1,
  "has_next": false,
  "has_prev": false
}

2.3 Lấy chi tiết cuộc hội thoại

GET /v1/conversations/{conversation_id}

Response gồm thông tin conversation và danh sách messages:

{
  "id": "6657f2d8a0f0f2a1a1111111",
  "name": "Tư vấn thành lập công ty",
  "message_count": 2,
  "messages": [
    {
      "id": "6657f3a0a0f0f2a1a2222222",
      "conversation_id": "6657f2d8a0f0f2a1a1111111",
      "role": "user",
      "content": "Điều kiện thành lập công ty TNHH là gì?",
      "metadata": {},
      "created_at": "2026-05-28T03:01:00.000Z"
    },
    {
      "id": "6657f3c1a0f0f2a1a3333333",
      "conversation_id": "6657f2d8a0f0f2a1a1111111",
      "role": "assistant",
      "content": "Theo quy định pháp luật hiện hành...",
      "metadata": {
        "references": []
      },
      "created_at": "2026-05-28T03:01:10.000Z"
    }
  ]
}

2.4 Đổi tên cuộc hội thoại

PATCH /v1/conversations/{conversation_id}
Content-Type: application/json

Request body:

{
  "name": "Hỏi đáp Luật Doanh nghiệp"
}

2.5 Xóa cuộc hội thoại

DELETE /v1/conversations/{conversation_id}

Response thành công: 204 No Content.


3. Chat không streaming

Endpoint này phù hợp khi Front-end muốn nhận toàn bộ câu trả lời một lần.

POST /v1/chat
Content-Type: application/json

Request body tối thiểu:

{
  "query": "Điều kiện thành lập công ty TNHH là gì?",
  "mode": "mix",
  "include_references": true
}

Request body có conversation:

{
  "conversation_id": "6657f2d8a0f0f2a1a1111111",
  "query": "Vậy hồ sơ đăng ký gồm những gì?",
  "mode": "mix",
  "include_references": true
}

Response:

{
  "conversation_id": "6657f2d8a0f0f2a1a1111111",
  "message_id": "6657f3c1a0f0f2a1a3333333",
  "response": "Theo quy định pháp luật hiện hành...",
  "references": [
    {
      "reference_id": "1",
      "file_path": "Luật Doanh Nghiệp 2020.txt"
    }
  ]
}

Tham số chat thường dùng

FieldTypeRequiredDefaultMô tả
querystringCâu hỏi của người dùng, tối thiểu 3 ký tự
conversation_idstringKhôngnullID cuộc hội thoại. Không truyền thì tự tạo mới
modestringKhôngmixChế độ tìm kiếm. Khuyến nghị dùng mix
include_referencesbooleanKhôngtrueCó trả về tài liệu tham khảo hay không
llm_providerstringKhôngnullModel tùy chọn. Thường không cần truyền
response_typestringKhôngnullGợi ý định dạng trả lời, ví dụ Bullet Points

Các giá trị mode hỗ trợ:

ModeMô tả
mixKhuyến nghị, kết hợp Knowledge Graph và Vector Search
localTập trung vào entity và quan hệ trực tiếp
globalNgữ cảnh rộng từ toàn bộ knowledge graph
hybridKết hợp local và global
naiveVector search đơn giản
bypassGọi LLM trực tiếp, không dùng RAG

4. Chat streaming

Endpoint này phù hợp cho UI chat real-time, hiển thị câu trả lời từng phần.

POST /v1/chat/stream
Content-Type: application/json

Request body:

{
  "conversation_id": "6657f2d8a0f0f2a1a1111111",
  "query": "Điều kiện thành lập công ty TNHH là gì?",
  "mode": "mix",
  "include_references": true
}

Response là NDJSON, mỗi dòng là một JSON object riêng:

{"stream_id":"b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa","conversation_id":"6657f2d8a0f0f2a1a1111111","type":"stream_started"}
{"stream_id":"b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa","type":"chunk","references":[{"reference_id":"1","file_path":"Luật Doanh Nghiệp 2020.txt"}],"response":null}
{"stream_id":"b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa","type":"chunk","references":null,"response":"Theo Luật Doanh nghiệp "}
{"stream_id":"b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa","type":"chunk","references":null,"response":"2020, điều kiện thành lập..."}
{"stream_id":"b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa","type":"stream_finished","status":"completed"}

Cách xử lý phía Front-end:

  • Lưu stream_id từ dòng stream_started.
  • Nếu object có references, lưu lại để hiển thị nguồn tham khảo.
  • Nếu object có response, nối dồn vào nội dung assistant message.
  • Khi nhận stream_finished, kết thúc trạng thái loading.

Ví dụ JavaScript:

const response = await fetch('https://luatvietnam-api.lumination.vn/v1/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': '<API_KEY_DUOC_CAP>'
  },
  body: JSON.stringify({
    conversation_id: '6657f2d8a0f0f2a1a1111111',
    query: 'Điều kiện thành lập công ty TNHH là gì?',
    mode: 'mix',
    include_references: true
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let answer = '';
let references = [];
let streamId = null;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop();

  for (const line of lines) {
    if (!line.trim()) continue;

    const event = JSON.parse(line);
    if (event.stream_id) streamId = event.stream_id;
    if (event.references) references = event.references;
    if (event.response) answer += event.response;
    if (event.type === 'stream_finished') {
      console.log('done', { answer, references, streamId });
    }
  }
}

5. Dừng stream đang chạy

Khi cần dừng câu trả lời đang streaming:

POST /v1/chat/streams/{stream_id}/abort

Response:

{
  "stream_id": "b4d0d4d2-1111-4444-8888-aaaaaaaaaaaa",
  "aborted": true
}
stream_id được trả về ở dòng đầu tiên của response streaming.

6. Quản lý tài liệu

6.1 Lấy danh sách tài liệu

GET /v1/documents?page=1&page_size=20

Response:

{
  "items": [
    {
      "id": "66580000a0f0f2a1a4444444",
      "kind": "file",
      "name": "Luật Doanh nghiệp 2020.pdf",
      "filename": "Luật Doanh nghiệp 2020.pdf",
      "content_type": "application/pdf",
      "size_bytes": 1024000,
      "status": "success",
      "index_track_id": "upload_20260528_100000_abc123",
      "created_at": "2026-05-28T03:00:00.000Z",
      "updated_at": "2026-05-28T03:00:00.000Z"
    }
  ],
  "page": 1,
  "page_size": 20,
  "total_count": 1,
  "total_pages": 1,
  "has_next": false,
  "has_prev": false
}

Có thể lọc theo status:

GET /v1/documents?page=1&page_size=20&status_filter=processed

6.2 Lấy chi tiết tài liệu

GET /v1/documents/{document_id}

6.3 Upload file tài liệu

POST /v1/documents/upload
Content-Type: multipart/form-data

Form data:

FieldTypeRequiredMô tả
fileFileFile cần upload
namestringKhôngTên hiển thị
metadata_jsonstringKhôngMetadata dạng JSON string nếu cần

Ví dụ JavaScript:

const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('name', 'Luật Doanh nghiệp 2020');

const response = await fetch('https://luatvietnam-api.lumination.vn/v1/documents/upload', {
  method: 'POST',
  headers: {
    'x-api-key': '<API_KEY_DUOC_CAP>'
  },
  body: form
});

const data = await response.json();

File upload được validate:

RuleGiá trị
Extension hỗ trợ.txt, .pdf, .docx, .md, .html
Kích thước tối đaTheo cấu hình hệ thống, mặc định 50MB
File rỗngKhông hợp lệ

Response:

{
  "id": "66580000a0f0f2a1a4444444",
  "kind": "file",
  "name": "Luật Doanh nghiệp 2020",
  "filename": "luat-doanh-nghiep-2020.pdf",
  "content_type": "application/pdf",
  "size_bytes": 1024000,
  "status": "success",
  "index_track_id": "upload_20260528_100000_abc123",
  "created_at": "2026-05-28T03:00:00.000Z",
  "updated_at": "2026-05-28T03:00:00.000Z"
}

6.4 Thêm tài liệu dạng text

POST /v1/documents/text
Content-Type: application/json

Request body:

{
  "text": "Điều 17 Luật Doanh nghiệp 2020 quy định...",
  "file_source": "luat_doanh_nghiep_2020_dieu_17",
  "metadata": {
    "source": "internal"
  }
}

Response:

{
  "id": "66580000a0f0f2a1a4444444",
  "kind": "text",
  "name": "luat_doanh_nghiep_2020_dieu_17",
  "status": "success",
  "index_track_id": "insert_20260528_100000_abc123",
  "created_at": "2026-05-28T03:00:00.000Z",
  "updated_at": "2026-05-28T03:00:00.000Z"
}

6.5 Kiểm tra trạng thái xử lý tài liệu

Sau khi upload hoặc thêm text, dùng endpoint này để biết tài liệu đã index xong chưa.

GET /v1/documents/{document_id}/status

Response:

{
  "id": "66580000a0f0f2a1a4444444",
  "status": "processed",
  "index_track_id": "upload_20260528_100000_abc123",
  "live_status": {
    "track_id": "upload_20260528_100000_abc123",
    "total_count": 1,
    "status_summary": {
      "processed": 1
    },
    "documents": [
      {
        "id": "doc-abc123",
        "status": "processed",
        "chunks_count": 220,
        "error_msg": null,
        "file_path": "Luật Doanh nghiệp 2020.pdf"
      }
    ]
  }
}

Các trạng thái thường gặp:

StatusÝ nghĩa
pendingĐang chờ xử lý
processingĐang xử lý
preprocessedĐã chia chunk, chờ indexing
processedHoàn thành, có thể hỏi đáp
failedXử lý lỗi
deletedĐã xóa

6.6 Cập nhật metadata tài liệu

PATCH /v1/documents/{document_id}
Content-Type: application/json

Request body:

{
  "name": "Luật Doanh nghiệp 2020 - bản cập nhật",
  "metadata": {
    "category": "doanh_nghiep"
  }
}

6.7 Xóa tài liệu

DELETE /v1/documents/{document_id}

Response thành công: 204 No Content.


6.8 Kiểm tra trạng thái pipeline indexing

GET /v1/documents/pipeline-status

Response:

{
  "busy": true,
  "job_name": "Indexing Files",
  "docs": 220,
  "batchs": 55,
  "cur_batch": 12,
  "latest_message": "Chunk 48 of 220 extracted 15 Ent + 14 Rel"
}

7. Mã lỗi thường gặp

HTTP CodeÝ nghĩaCách xử lý
400Request không hợp lệKiểm tra body, query hoặc ID truyền lên
401Sai hoặc thiếu x-api-keyKiểm tra API key
404Không tìm thấy resourceKiểm tra conversation_id hoặc document_id
413File upload quá lớnGiảm kích thước file
422Body không đúng schemaKiểm tra field required và kiểu dữ liệu
429Vượt rate limitRetry sau ít nhất 60 giây
502Lỗi từ AI backendRetry sau vài giây hoặc liên hệ đội vận hành
500Lỗi hệ thốngLiên hệ đội vận hành

8. Gợi ý tích hợp Front-end

  • Dùng /v1/chat/stream cho trải nghiệm chat tốt nhất.
  • Dùng /v1/chat nếu cần response một lần, đơn giản hơn.
  • Luôn lưu conversation_id để tiếp tục hội thoại.
  • Khi streaming, ghép dồn các field response để tạo nội dung cuối.
  • Hiển thị references nếu có để người dùng biết nguồn tham khảo.
  • Với upload tài liệu, nên gọi /v1/documents/{document_id}/status định kỳ cho đến khi status là processed hoặc failed.