All Products
Search
Document Center

Vector Retrieval Service for Milvus:Buat aplikasi pengambilan kasus hukum dengan basis pengetahuan Alibaba Cloud Milvus

Last Updated:Aug 28, 2026

Basis pengetahuan Alibaba Cloud Milvus dapat mengubah undang-undang dan peraturan publik, putusan pengadilan, serta kebijakan kepatuhan perusahaan menjadi asisten materi hukum yang dapat dicari: ambil kasus serupa berdasarkan rincian kasus, ringkas pendapat yudisial, dan tampilkan sumber aslinya.

Solusi

Pipeline end-to-end identik dengan yang terdapat dalam Buat aplikasi Q&A layanan pelanggan cerdas menggunakan basis pengetahuan Alibaba Cloud Milvus: definisikan tag di Konsol → impor dokumen sumber secara batch berdasarkan tag → terbitkan versi → pengambilan SDK dengan penyaringan tag opsional → model LLM menghasilkan jawaban dengan kutipan sumber → Flask menyajikan halaman Q&A. Gunakan kembali kode rekayasa dari tutorial tersebut secara langsung: kb_client.py, upload.py, app.py, templates/index.html, dan start.sh. Topik ini hanya mencakup bagian-bagian yang harus diubah untuk skenario hukum: tag kasus (termasuk tipe tag numerik), parameter pengambilan, batasan prompt, dan penanganan hasil kosong yang harus Anda tambahkan.

Untuk versi pertama, pilih satu jenis kejahatan atau satu topik kepatuhan saja dan impor hanya 10–50 dokumen sumber. Perluas cakupan setelah validasi. Seluruh proses membutuhkan waktu sekitar 25–40 menit. Waktu penguraian dokumen bergantung pada jumlah dan ukuran dokumen sumber.

Solusi ini merupakan alat pendukung untuk pengambilan materi dan tidak menghasilkan opini hukum. Pertahankan langkah tinjauan manual baik untuk hasil pengambilan maupun ringkasan yang dihasilkan model.

Prasyarat

  • Basis pengetahuan Milvus telah dibuat, dan Anda telah mencatat ID basis pengetahuan (misalnya, kd-803ae9b10cc31).

  • Anda telah membuat RAM user di bawah Akun Alibaba Cloud Anda, memilih Use permanent AccessKey, dan menyambungkan kebijakan sistem AliyunMilvusFullAccess.

  • Anda telah menyiapkan titik akhir dan Kunci API dari model bahasa besar yang mendukung protokol OpenAI chat/completions.

  • Python 3.8 atau versi lebih baru telah diinstal secara lokal, dan direktori proyek telah disiapkan sesuai panduan.

  • Pemeriksaan otorisasi dan de-identifikasi dokumen sumber Anda telah selesai. Untuk detailnya, lihat Catatan untuk skenario hukum.

Langkah 1: Definisikan tag kasus

Pada halaman detail basis pengetahuan, di bawah Basic Information, pilih Tags > Manage dan tambahkan keempat tag berikut. Pilih tipe bidang dari daftar drop-down di sebelah kanan kotak input nama tag. Opsi yang tersedia adalah string, int64, list, float32, dan bool.

Nama tag

Tipe bidang

Deskripsi

Contoh nilai

docType

string

Jenis dokumen

Court judgment, Laws and regulations, Compliance policy

court

string

Pengadilan tingkat pertama

The First People's Court of XX City

caseType

string

Alasan gugatan

Contract fraud, Causing a traffic accident

judgmentYear

int64

Tahun putusan

2025

Mendefinisikan tahun putusan sebagai int64 tidak mengaktifkan kueri rentang. API pengambilan tidak mendukung ekspresi rentang integer. Tujuan mendefinisikan tahun putusan sebagai int64 adalah agar server mengonversi string numerik menjadi integer, sehingga operator =, in, dan not in berfungsi dengan benar. Oleh karena itu, untuk kebutuhan seperti "kasus dari tiga tahun terakhir", klien harus terlebih dahulu menghitung daftar tahun tersebut lalu meneruskannya dengan in, misalnya [2024, 2025, 2026]. Jangan gunakan atau dalam kondisi tag_filter. Saat rentang tahun besar, tidak ada alternatif yang sama efisiennya — pecah menjadi beberapa kueri.

Peringatan

Kotak dialog manajemen tag disimpan secara keseluruhan, dan daftar tag dimuat secara asinkron setelah kotak dialog dibuka. Tunggu hingga semua tag yang ada ditampilkan sebelum menambahkan tag baru dan mengklik Done. Jika tidak, penyimpanan dapat menimpa semuanya dengan "daftar kosong + tag baru", menghapus definisi tag yang sudah ada.

Perhatikan hal berikut mengenai tipe dan nilai tag:

  • Untuk tag bertipe int64, Anda dapat langsung menulis angka JSON biasa (seperti 2025) di documents.jsonl. Saat penyaringan, value akan cocok baik Anda meneruskan angka maupun string.

  • Nilai tag dapat berupa string kosong. Undang-undang dan peraturan serta kebijakan kepatuhan tidak memiliki pengadilan tingkat pertama, sehingga Anda dapat menulis "court": "". Konsol menampilkannya sebagai court=, dan Anda nanti dapat menggunakan court = "" sebagai kondisi filter untuk mencocokkan tepat dokumen sumber tersebut.

Langkah 2: Siapkan dokumen sumber dan manifes impor

  • Letakkan dokumen sumber di direktori documents/. Format PDF, DOCX, Markdown, TXT, dan lainnya didukung. Pastikan nomor kasus, pengadilan, dan tanggal putusan tetap berada di teks isi atau nama file. Dalam pengujian kami, setelah menulis nomor kasus di baris pertama isi dokumen, kami dapat langsung mengambil putusan yang sesuai berdasarkan nomor kasus tersebut.

  • Buat file documents.jsonl dan anotasi setiap dokumen sumber dengan jenis dokumen, pengadilan, alasan gugatan, dan tahun putusan:

    {"path": "documents/criminal-case-001.md", "metadata": {"docType": "Court judgment", "court": "The First People's Court of XX City", "caseType": "Contract fraud", "judgmentYear": 2025}}
    {"path": "documents/criminal-case-002.md", "metadata": {"docType": "Court judgment", "court": "The Second People's Court of XX City", "caseType": "Contract fraud", "judgmentYear": 2023}}
    {"path": "documents/law-excerpt.md", "metadata": {"docType": "Laws and regulations", "court": "", "caseType": "Criminal", "judgmentYear": 2024}}
    {"path": "documents/compliance-policy.md", "metadata": {"docType": "Compliance policy", "court": "", "caseType": "Compliance", "judgmentYear": 2024}}
  • Putusan pengadilan harus mempertahankan konteks fakta kasus, alasan putusan, dan kesimpulan. Pada halaman detail basis pengetahuan, klik Create Policy di bawah Processing Policy untuk menyesuaikan granularitas chunk. Unit panjang maksimum chunk adalah karakter (default 512). Atur menjadi 770–1.150 karakter (sekitar 512–768 token) agar isu-isu utama dalam sengketa dan alasan putusan masuk ke dalam chunk yang sama sebisa mungkin.

  • Impor kasus dengan kesimpulan berbeda di bawah alasan gugatan yang sama. Nilai pengambilan hukum justru terletak pada penyajian ketidaksepakatan. Dalam pengujian kami, setelah mengimpor dua putusan penipuan kontrak dengan kesimpulan berlawanan, model mengutip keduanya dan secara eksplisit menunjukkan bahwa "satu kasus mengakui kejahatan bersama, sedangkan yang lain tidak karena kurangnya bukti persekongkolan". Hal ini lebih bernilai sebagai referensi daripada mengimpor materi dengan satu kesimpulan saja. Tuntut dalam prompt agar kasus semacam ini disajikan secara terpisah, sehingga model tidak menyajikan kesimpulan kasus individual sebagai aturan umum.

Langkah 3: Konfigurasikan parameter pengambilan dan prompt

Dalam config.json, sesuaikan aliyun.knowledge_base_version, retrieval, dan scenario untuk skenario hukum. Contoh berikut hanya menampilkan ketiga blok ini. Pertahankan blok lain dalam config.json Anda dari tutorial yang dirujuk, termasuk ID basis pengetahuan serta titik akhir dan Kunci API LLM yang Anda siapkan di Prasyarat.

{
  "aliyun": {
    "knowledge_base_version": "LATEST_PUBLISHED"
  },
  "retrieval": {
    "page_size": 8,
    "candidate_count": 80,
    "min_score": 0.25,
    "semantic_weight": 0.4,
    "enable_query_expansion": true,
    "rerank_model_name": "qwen3-rerank",
    "tag_filter": {
      "relation": "and",
      "conditions": [
        {"field": "docType", "op": "=", "value": "Court judgment"}
      ]
    }
  },
  "scenario": {
    "title": "Pengambilan kasus hukum dan kepatuhan",
    "system_prompt": "Anda adalah asisten pengambilan materi hukum. Jangan memberikan opini hukum akhir. Ringkas fakta, isu utama dalam sengketa, serta pendapat yudisial dan dasarnya secara ketat dari materi yang diambil, dan anotasi setiap item dengan [Source N]. Saat kasus berbeda mencapai kesimpulan yang bertentangan, sajikan secara terpisah. Jika materi yang diambil kosong atau tidak relevan dengan pertanyaan, balas hanya dengan 'Materi tidak mencukupi; tinjauan manual direkomendasikan', dan jangan pernah mengutip undang-undang, peraturan, interpretasi yudisial, atau kasus yang tidak muncul dalam materi yang diambil.",
    "image_enabled": false,
    "sample_questions": [
      "Ketika seseorang menipu pembayaran barang dengan memalsukan kemampuan melaksanakan kontrak, bagaimana kejahatan bersama dalam penipuan kontrak ditentukan?",
      "Bagaimana penyerahan diri sukarela setelah menyebabkan kecelakaan lalu lintas memengaruhi hukuman?",
      "Kasus mana yang membahas perbedaan antara pelaku utama dan kaki tangan?"
    ]
  }
}

Perhatikan hal berikut mengenai parameter kunci:

  • semantic_weight=0.4: pengambilan hukum sangat bergantung pada nomor kasus, jenis kejahatan, dan terminologi hukum, sehingga turunkan bobot semantik dan naikkan bobot kata kunci secara proporsional. Dalam pengujian kami, menanyakan dengan nomor kasus lengkap berhasil mengenai putusan yang sesuai secara tepat. Anda dapat menyetel nilai ini dengan menggunakan scoreDetails dalam hasil pengambilan, yang berisi keywordScore dan semanticScore.

  • candidate_count=80 dengan qwen3-rerank diaktifkan: perluas set kandidat dan biarkan model penyusunan ulang mengurutkan kandidat berdasarkan kemiripan dengan kasus serupa. Perhatikan bahwa skor rerank dan skor vektor tidak berada pada skala yang sama. Dikombinasikan dengan min_score, keduanya dapat menyaring beberapa hasil. Saat menyetel, tetapkan salah satunya terlebih dahulu.

  • Pertahankan knowledge_base_version diatur ke LATEST_PUBLISHED kecuali pelacakan kepatuhan mengharuskan versi tertentu. Untuk detail tentang penjepitan versi dan penghapusan, lihat Kelola versi yang diterbitkan.

Hanya tiga operator yang berfungsi untuk penyaringan tag

Dalam pengujian kami, pada versi saat ini, hanya =, in, dan not in dalam tag_filter.conditions yang benar-benar berlaku sebagai nilai op:

Operator

Perilaku

Contoh

=

Pencocokan eksak; untuk tag int64, meneruskan angka atau string keduanya berfungsi

{"field": "judgmentYear", "op": "=", "value": 2025}

in

Pencocokan enumerasi

{"field": "judgmentYear", "op": "in", "value": [2024, 2025]}

not in

Mengecualikan enumerasi

{"field": "docType", "op": "not in", "value": ["Compliance policy"]}

>, , <,

Kondisi diabaikan dan semua data dikembalikan (tidak ada error yang muncul)

, empty, not empty, start with, end with

Kondisi diabaikan dan semua data dikembalikan

contains, not contains

Alias dari in/not in, bukan pencarian substring; meneruskan fragmen string menghasilkan 0 hasil

Jika Anda meneruskan operator yang tidak berlaku, API tidak menampilkan error dan mengembalikan semua data tanpa penyaringan. Dalam skenario hukum, ini berarti kasus yang seharusnya dikecualikan tetap masuk ke konteks LLM, dan tidak ada yang tampak salah di halaman. Oleh karena itu:

  • Jangan gunakan > atau untuk menyaring rentang tahun. Gunakan in dengan enumerasi tahun, misalnya {"field": "judgmentYear", "op": "in", "value": [2023, 2024, 2025]}.

  • Jangan gunakan empty untuk memeriksa tag kosong. Gunakan {"field": "court", "op": "=", "value": ""} sebagai gantinya.

  • Setelah mengonfigurasi kondisi filter, selalu bandingkan jumlah total hasil dengan hasil tanpa filter untuk memastikan filter benar-benar berlaku. Jika keduanya identik, kondisi tersebut tidak diterapkan.

    Jika op ditulis sebagai alias seperti eq, ==, atau like, API mengembalikan 400 Unsupported tag filter operator, dan setiap pertanyaan gagal. "Operator yang didukung" yang tercantum dalam pesan error tersebut mencakup operator dari tabel di atas yang tidak berlaku, sehingga tidak dapat dianggap sebagai daftar yang dapat digunakan.

Langkah 4: Tangkap hasil pengambilan kosong di app.py

Dalam app.py yang digunakan kembali, fungsi llm_answer() masih memanggil LLM meskipun hasil pengambilan kosong. Konteksnya kemudian menjadi string kosong, dan model menjawab sepenuhnya dari pengetahuannya sendiri. Dalam pengujian kami, kami mengajukan pertanyaan yang tidak tercakup dalam basis pengetahuan, seperti "Bagaimana perhitungan ganti rugi untuk pelanggaran hak kekayaan intelektual?". Model menghasilkan aturan perhitungan ganti rugi yang panjang dan membuat anotasi sumber palsu seperti [Source 1: Interpretation of ... Punitive Damages, Article 2], meskipun sources kosong. Dalam skenario hukum, output semacam ini sangat menyesatkan dan harus dicegat di tingkat kode:

def llm_answer(question: str, results: list[dict[str, Any]]) -> str:
    if not LLM.get("enabled", True):
        return "LLM dinonaktifkan; silakan lihat hasil pengambilan di bawah ini."
    if not results:
        return "Tidak ditemukan materi terkait pertanyaan ini dalam basis pengetahuan, sehingga saya tidak dapat menjawab. Tambahkan materi yang relevan dan coba lagi, atau eskalasi ke tinjauan manual."
    ...

Batasan prompt saja tidak dapat diandalkan. Bahkan ketika system_prompt secara eksplisit menyatakan "nyatakan dengan jelas ketika materi tidak mencukupi", model tetap menjawab. Setelah menambahkan fallback di atas, pertanyaan yang tidak tercakup secara konsisten mengembalikan pesan tersebut, dan pertanyaan normal dengan hasil pengambilan tidak terpengaruh.

Langkah 5: Unggah, terbitkan, dan verifikasi

  1. Unggah dokumen sumber. MetaFields berlaku untuk seluruh batch; skrip mengelompokkan dokumen berdasarkan tag dan mengirimkannya secara batch.

    python upload.py --manifest documents.jsonl
  2. Pada halaman Data Management di Konsol, pastikan status dokumen adalah Processed. Respons sukses dari API unggah hanya berarti penguraian asinkron telah dikirim.

  3. Pada halaman Version Management, klik Publish Version, selesaikan wizard, dan pastikan status versi baru adalah Published. Jika tombol tersebut dinonaktifkan, hapus terlebih dahulu versi lama yang tidak lagi diperlukan. Lihat Kelola versi yang diterbitkan.

  4. Jalankan layanan.

    python app.py
  5. Setelah layanan berjalan, ajukan pertanyaan uji:

    curl -sS http://127.0.0.1:7860/api/ask \
      -H 'Content-Type: application/json' \
      -d '{"question":"Ketika seseorang menipu pembayaran barang dengan memalsukan kemampuan melaksanakan kontrak, bagaimana kejahatan bersama dalam penipuan kontrak ditentukan?"}'
  • Halaman terbuka secara normal, dan mengirimkan pertanyaan mengembalikan jawaban beserta sumber pengambilannya.

  • Setiap [Source N] dalam jawaban berkorespondensi dengan chunk sumber di bagian sources di bawahnya.

  • Menanyakan dengan nomor kasus lengkap berhasil mengenai putusan pengadilan yang sesuai secara tepat.

  • Saat Anda menanyakan konten yang tidak tercakup dalam basis pengetahuan, respons mengembalikan pesan "Materi tidak mencukupi" dan sama sekali tidak mengandung kutipan hukum apa pun. Pastikan untuk menguji hal ini secara praktis — ini adalah kriteria penerimaan paling kritis untuk skenario ini.

  • Setelah menambahkan lebih banyak materi dan menerbitkan versi baru, halaman dapat mengambil konten baru tersebut.

Kelola versi yang diterbitkan

LATEST_PUBLISHED secara otomatis menggunakan versi terbaru yang diterbitkan. Anda juga dapat menentukan nomor versi eksplisit (seperti v2) untuk menjepit versi tertentu. Skenario kepatuhan biasanya memerlukan pelacakan versi materi mana yang mendukung keputusan tertentu, sehingga catat nomor versi yang benar-benar digunakan dalam log panggilan aplikasi.

Penting

Setelah versi dihapus, versi tersebut langsung menjadi tidak dapat diambil, dan backend membersihkan datanya secara asinkron sesudahnya. Sebelum menghapus versi, alihkan terlebih dahulu aplikasi apa pun yang masih menjepit versi tersebut ke versi baru. Jika Anda menghapus versi yang sedang digunakan aplikasi, pengambilan langsung mengembalikan 404 Knowledge base version ... does not exist, dan setiap pertanyaan gagal di halaman.

Paling banyak tiga versi yang diterbitkan dapat ada secara bersamaan. Setelah batas tercapai, tombol Publish Version dinonaktifkan, meskipun halaman masih menampilkan "Ada N perubahan tertunda". Hapus terlebih dahulu versi lama yang tidak lagi diperlukan dari catatan versi. Jika Anda menjepit versi, Anda juga harus menetapkan proses pembaruan konfigurasi sebelum menghapus versi lama.

Catatan untuk skenario hukum

Sebelum membagikan aplikasi kepada pengguna akhir, tinjau pertimbangan berikut:

  • Hanya materi yang sah — Gunakan hanya materi yang Anda izinkan untuk dipublikasikan dan diproses, dan selesaikan pemeriksaan otorisasi sebelum mengunggah. Jika putusan pengadilan berisi informasi pribadi, lakukan de-identifikasi terlebih dahulu. Chunk dokumen dikirim ke LLM sebagai konteks, yang merupakan bentuk egress data.

  • Penafian permanen — Halaman harus mencantumkan penafian permanen. Halaman contoh hanya menyatakan "Jawaban dihasilkan dari konten basis pengetahuan yang diterbitkan". Ubah pemberitahuan di templates/index.html agar secara eksplisit menyatakan: "Hasil ini hanya merupakan alat bantu pengambilan materi dan bukan merupakan opini hukum. Mintalah tinjauan oleh profesional."

  • Titik masuk terpisah berdasarkan jenis dokumen — Misalnya, batasi titik masuk konsultasi publik dengan docType = Laws and regulations agar hanya mengambil undang-undang dan peraturan publik, sedangkan titik masuk analisis internal juga mengizinkan putusan pengadilan.

  • Penerapan produksi — Jangan terus menggunakan server pengembangan Flask. Beralihlah ke server WSGI produksi dan tambahkan manajemen rahasia, otentikasi, audit, dan Pembatasan kecepatan.

FAQ

Gejala

Penyebab dan solusi

Setiap pertanyaan mengembalikan 404 Knowledge base version ... does not exist

Nomor versi yang dikodekan keras dalam konfigurasi telah dihapus atau belum pernah diterbitkan. Gunakan LATEST_PUBLISHED, atau tentukan nama versi yang benar-benar ada di halaman Version Management.

Pertanyaan mengembalikan 500, dan log menunjukkan 400 Unsupported tag filter operator

op menggunakan alias seperti eq, ==, atau like. Gunakan =, in, atau not in sebagai gantinya.

Jumlah hasil dengan penyaringan tag persis sama dengan tanpa penyaringan

Anda menggunakan operator yang tidak berlaku (seperti >, , , atau empty). Gunakan =, in, atau not in sebagai gantinya. Lihat Langkah 3.

Penyaringan rentang tahun tidak berpengaruh

Operator perbandingan numerik tidak berlaku. Gunakan in dengan enumerasi tahun.

Penyaringan tag selalu mengembalikan 0 hasil

Nama tag dieja berbeda dari yang ditulis. API tidak menampilkan error dan hanya mengembalikan 0 hasil. Verifikasi di bawah Tags > Manage pada halaman detail basis pengetahuan. Dalam pengujian kami, operator contains juga mengembalikan 0 hasil.

Mengajukan pertanyaan yang tidak tercakup dalam basis pengetahuan, tetapi mendapatkan kutipan hukum yang tampak masuk akal

llm_answer() masih memanggil LLM meskipun hasil pengambilan kosong. Tambahkan fallback hasil kosong dari Langkah 4.

Bidang tags dalam hasil pengambilan kosong

Versi saat ini tidak mengisi kembali tag. Bidang tags tidak mengembalikan pengadilan dan tahun putusan yang Anda tulis saat unggah. Ini adalah bidang yang berbeda dari MetaFields pada AddDocuments, dan tidak ada parameter untuk mengaktifkan pengembaliannya. Nilai kosong tidak berarti unggah gagal. Jika Anda perlu menampilkan informasi ini dalam jawaban, gabungkan hasil pengambilan dengan documents.jsonl berdasarkan documentId dan tambahkan ke konteks.

Unggah mengembalikan 400 No OSS document can be registered.

Setiap file dalam batch dideduplikasi karena nama file yang sama. Ganti nama file, atau hapus data lama di Konsol terlebih dahulu.

Pengambilan melaporkan kegagalan dengan code = None

Logika _check() dalam kode yang digunakan kembali salah (getattr(body, "code", 0) != 0): respons sukses memiliki code = None. Ubah menjadi getattr(body, "code", None) not in (None, 0, "0").

Setelah mengaktifkan reranking, jumlah hasil berkurang

Skor rerank dan skor vektor berada pada skala berbeda. Dikombinasikan dengan min_score, lebih banyak hasil tersaring. Turunkan min_score terlebih dahulu, atau nonaktifkan reranking untuk membandingkan.