All Products
Search
Document Center

Vector Retrieval Service for Milvus:Buat asisten troubleshooting pengembangan dengan basis pengetahuan Alibaba Cloud Milvus

Last Updated:Aug 28, 2026

Dalam tutorial ini, Anda membuat asisten troubleshooting pengembangan berbasis basis pengetahuan Alibaba Cloud Milvus yang menyimpan referensi API, catatan arsitektur, Runbook, dan postmortem. Anda dapat mencari berdasarkan nama API atau kode kesalahan serta mendapatkan langkah-langkah troubleshooting terstruktur lengkap dengan kutipan sumber.

Ikhtisar solusi

Tutorial ini membangun di atas Buat aplikasi Q&A layanan pelanggan cerdas dengan basis pengetahuan Alibaba Cloud Milvus. Alur end-to-end-nya identik: definisikan tag di Konsol → impor file sumber secara batch berdasarkan tag → publikasikan versi → ambil melalui SDK (dengan filter tag opsional) → minta LLM menghasilkan jawaban dengan kutipan sumber → sajikan halaman Q&A menggunakan Flask. Anda menggunakan kembali kode rekayasa (kb_client.py, upload.py, app.py, templates/index.html, dan start.sh) dari tutorial tersebut, dengan dua modifikasi yang dijelaskan di Langkah 4: Adaptasi kode yang digunakan kembali. Dokumen ini hanya mencakup perubahan yang harus Anda lakukan untuk skenario troubleshooting pengembangan: tag modul, parameter pengambilan untuk istilah eksak, penanganan file sumber HTML, serta pembatasan terhadap perintah berisiko tinggi dan hasil kosong.

Untuk versi pertama, pilih hanya 5 hingga 20 file sumber dari satu sistem saja, lalu perluas cakupannya setelah validasi. Seluruh proses memakan waktu sekitar 20 hingga 30 menit, dan waktu parsing dokumen bergantung pada jumlah serta ukuran file sumber.

Prasyarat

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

  • Pengguna RAM telah dibuat dengan Akun Alibaba Cloud Anda, dengan opsi Use Permanent AccessKey Access dipilih dan kebijakan sistem AliyunMilvusFullAccess dilampirkan.

  • Titik akhir LLM yang mendukung protokol OpenAI chat/completions beserta Kunci API-nya telah siap.

  • Python 3.8 atau versi lebih baru telah diinstal secara lokal.

  • Direktori proyek dan lima file yang digunakan kembali (kb_client.py, upload.py, app.py, templates/index.html, dan start.sh) telah disiapkan dengan mengikuti tutorial yang dirujuk di Ikhtisar solusi.

  • File sumber tidak berisi rahasia, token, atau akun jaringan internal.

Langkah 1: Definisikan tag modul

Di bawah Basic Information pada halaman detail basis pengetahuan, pilih Tags > Manage dan tambahkan tiga tag berikut. Atur tipe bidang masing-masing tag menjadi string. Menu dropdown tipe berada di sisi kanan kotak input nama tag, dengan opsi string, int64, list, float32, dan bool.

Nama tagDeskripsiContoh nilai
moduleSistem atau layanan tempat file sumber berasalorder-service, user-service
docTypeJenis dokumenAPI, Runbook, ErrorCode, Postmortem
versionVersi API atau dokumenv2

Nama tag version memiliki nama yang sama dengan parameter version yang merepresentasikan versi basis pengetahuan yang dipublikasikan dalam permintaan pengambilan, tetapi keduanya tidak saling memengaruhi: tag digunakan dalam tagFilter.field, sedangkan versi pengambilan berada di level teratas permintaan. Jika Anda khawatir terjadi kebingungan, beri nama tag tersebut apiVersion sebagai gantinya.

Peringatan

Kotak dialog manajemen tag disimpan secara keseluruhan. Setelah Anda membuka kotak dialog, daftar tag dimuat secara asinkron. Tunggu hingga semua tag yang ada ditampilkan sebelum menambahkan tag baru dan mengklik OK. Jika tidak, penyimpanan dapat menimpa seluruh isi dengan "daftar kosong + tag baru" dan menghapus definisi tag yang sudah ada.

Tag module merupakan keputusan desain paling kritis dalam skenario ini. Sistem yang berbeda sering kali memiliki path API dengan nama yang persis sama, dan tanpa filter modul, hasilnya akan saling mengganggu. Dalam pengujian kami, user-service dan order-service sama-sama memiliki path GET /api/v2/orders/{orderId}. Saat kami mencari path ini:

Kondisi pengambilanHasil
Tanpa filterFile sumber user-service berada di peringkat pertama (relevansi 0.246) — modul yang salah terpilih
module = order-serviceFile sumber order-service berada di peringkat pertama, dan file sumber user-service sepenuhnya dikecualikan

Langkah 2: Siapkan file sumber dan manifes impor

Pada langkah ini, Anda mengumpulkan file sumber, menganotasi masing-masing dalam manifes impor, dan mengonfigurasi cara basis pengetahuan membaginya menjadi chunk.

  • Letakkan file sumber di direktori documents/. Format yang didukung meliputi Markdown, HTML, PDF, DOCX, dan TXT. Pertahankan kode kesalahan lengkap, path API, dan nomor versi dalam file sumber — dalam pengujian kami, baik kode kesalahan maupun path lengkap dapat diambil secara eksak.

  • Buat file documents.jsonl dan anotasi setiap file sumber dengan modul, jenis dokumen, dan versinya:

    {"path": "documents/order-api.md", "metadata": {"module": "order-service", "docType": "API", "version": "v2"}}
    {"path": "documents/order-timeout-runbook.md", "metadata": {"module": "order-service", "docType": "Runbook", "version": "v2"}}
    {"path": "documents/order-error-codes.html", "metadata": {"module": "order-service", "docType": "ErrorCode", "version": "v2"}}
    {"path": "documents/order-postmortem-2026-06.md", "metadata": {"module": "order-service", "docType": "Postmortem", "version": "v2"}}
  • Impor referensi API, Runbook, tabel kode kesalahan, dan postmortem sebagai satu set, dan bedakan menggunakan docType. Dalam pengujian kami, saat kami menanyakan tentang kode kesalahan, keempat jenis file sumber tersebut ditemukan sekaligus, dan model menghasilkan jawaban lengkap berupa "makna → langkah troubleshooting → kasus historis".

Penanganan file sumber HTML

HTML dapat diunggah dan diurai langsung, dan konten di dalam <table> ikut masuk ke indeks. Dalam pengujian kami, kueri ORD-42901, yang hanya ada dalam tabel kode kesalahan HTML, berhasil menemukan file tersebut secara eksak.

Namun, HTML memiliki granularitas chunk yang lebih kasar dibandingkan Markdown (dalam pengujian ini, satu file HTML berisi dua tabel diurai menjadi 1 chunk). Hal ini terkait dengan cara HTML diurai. Sebelum memilih format file sumber, pahami dua poin berikut:

  • Blok kode tidak mempertahankan tata letak aslinya. Tag <pre> dan <code> dikenali sebagai blok, tetapi teks diekstraksi secara rekursif dan digabung dengan spasi, sehingga indentasi, jeda baris, dan pembatas kode semuanya hilang. Untuk file sumber yang berisi banyak kode atau perintah, konversikan ke Markdown sebelum diimpor; jika tidak, potongan kode yang diambil mungkin tidak dapat digunakan langsung.

  • Tabel diindeks secara utuh. Elemen <table> ditambahkan sebagai segmen independen tunggal dalam bentuk string HTML aslinya dan tidak dibagi per baris, sehingga tabel besar mudah membentuk chunk kasar.

    Kesimpulan: teks deskriptif biasa dan tabel kecil dapat menggunakan HTML secara langsung. Jika Anda memerlukan ketepatan tinggi, pengambilan berdasarkan segmen kode, atau pemisahan tabel besar, lebih baik gunakan Markdown atau file sumber terstruktur, dan setelah impor, lakukan pemeriksaan acak terhadap chunk di halaman Data Management.

Konfigurasikan kebijakan chunking

Langkah troubleshooting dan contoh kode tidak boleh terpotong di tengah. Di halaman detail basis pengetahuan, klik Create Policy di bagian Processing Policy untuk menyesuaikan granularitas chunk. Satuan panjang segmen maksimum adalah karakter (default 512). Atur menjadi 580–770 karakter (sekitar 384–512 token) agar "satu langkah troubleshooting lengkap" atau "satu contoh kode" berada dalam chunk yang sama. Rasio karakter ke token bervariasi tergantung bahasa dan tokenizer file sumber Anda, jadi gunakan nilai karakter sebagai acuan dasar dan lakukan pemeriksaan acak terhadap chunk setelah impor.

Langkah 3: Konfigurasikan parameter pengambilan dan prompt

Kueri troubleshooting pengembangan umumnya berupa kode kesalahan, path API, dan perintah. Kueri ini termasuk dalam pencocokan istilah eksak, sehingga parameternya sangat berbeda dari skenario lain.

{
  "retrieval": {
    "page_size": 6,
    "candidate_count": 64,
    "min_score": 0.05,
    "semantic_weight": 0.15,
    "enable_query_expansion": false,
    "rerank_model_name": "",
    "tag_filter": {
      "relation": "and",
      "conditions": [
        {"field": "module", "op": "=", "value": "order-service"}
      ]
    }
  },
  "scenario": {
    "title": "Development docs and troubleshooting assistant",
    "system_prompt": "You are a development documentation assistant. Answer only based on the retrieved materials. Preserve API names, error codes, commands, and code as-is. List troubleshooting steps in order and cite them as [Source N]. When write operations or high-risk commands are involved, explicitly state the risk level and require manual confirmation. When the retrieved materials are empty, reply only that the materials are insufficient and warn against performing any change operation.",
    "image_enabled": false,
    "sample_questions": [
      "What are the required parameters for the order query API?",
      "In what order should I troubleshoot a connection timeout?",
      "In which documents does this error code appear?"
    ]
  }
}

Daftar berikut menjelaskan parameter yang disesuaikan untuk skenario ini. Bidang lain dalam contoh tersebut diwariskan dari tutorial yang dirujuk.

  • semantic_weight: 0.15: Faktor bobot skor akhir. Skor dihitung sebagai score ≈ (1-semantic_weight) × keywordScore + semantic_weight × semanticScore (fitur peringkat juga dapat ditambahkan), dan min_score melakukan filter pasca pada skor akhir ini. Skenario ini menggunakan 0.15 agar skor kata kunci dari istilah eksak seperti kode kesalahan dan path API mendominasi peringkat. Karena semantic_weight berinteraksi dengan min_score, sesuaikan keduanya bersama seperti dijelaskan di Sesuaikan semantic_weight dan min_score bersama.

  • enable_query_expansion: false: Ekspansi kueri dinonaktifkan agar kode kesalahan dan nama API tidak ditulis ulang. Dalam pengujian kami, setelah diaktifkan, keywordScore dari kueri ORD-50021 turun dari 0.283 menjadi 0.226, dan jumlah hasil yang diambil untuk kueri ORD-42901 turun dari 2 menjadi 1. Biarkan dinonaktifkan untuk pengambilan istilah eksak.

  • tag_filter mengunci module: Ini mencegah API dengan nama identik dari sistem berbeda saling mengganggu. Lihat Langkah 1: Definisikan tag modul untuk efeknya. Jika satu titik masuk perlu mencakup beberapa modul, gunakan {"field": "module", "op": "in", "value": ["order-service", "user-service"]}.

  • rerank_model_name kosong berarti penyusunan ulang tidak diaktifkan. Pencocokan eksak untuk kode kesalahan bergantung pada skor kata kunci, sehingga penyusunan ulang memberikan manfaat terbatas.

  • op hanya mendukung =, in, dan not in: Dalam pengujian kami, operator seperti , >, , <, , empty, not empty, start with, dan end with diabaikan diam-diam dan semua data dikembalikan (tanpa laporan kesalahan). Operator contains dan not contains hanyalah alias dari in/not in, bukan pencarian substring; memberikan fragmen string menghasilkan 0 hasil. Alias seperti eq, ==, dan like mengembalikan 400 Unsupported tag filter operator, dan setiap pertanyaan gagal. Setelah mengonfigurasi kondisi filter, bandingkan jumlah total hasil dengan hasil tanpa filter untuk memastikan filter benar-benar berlaku.

Sesuaikan semantic_weight dan min_score bersama

semantic_weight hanya mengubah skor tertimbang akhir; tidak mengubah dua sub-skor (keywordScore dan semanticScore) dalam scoreDetails dari hasil pengambilan. Skor tertimbang kira-kira:

score ≈ semantic_weight × semanticScore + (1 - semantic_weight) × keywordScore

Perhatikan dua poin berikut sebelum menyesuaikan:

  1. Menurunkan semantic_weight tidak selalu menurunkan skor total. Skor total hanya turun jika semanticScore dari batch hasil lebih tinggi daripada keywordScore-nya. Inilah alasan dokumen ini juga menurunkan min_score menjadi 0.05. Kedua parameter harus dikalibrasi bersama dengan memeriksa scoreDetails.

  2. Saat Anda mengatur semantic_weight ke 0, implementasi saat ini tidak lagi menerapkan ambang batas min_score. Jangan gunakan 0 untuk berarti "pengambilan murni berbasis kata kunci".

    Untuk materi pengembangan, keywordScore biasanya jauh lebih rendah daripada semanticScore (dalam pengujian kami, masing-masing sekitar 0.16–0.28 dan 0.64–0.78), sehingga dalam distribusi ini, menurunkan semantic_weight menarik skor total ke sisi yang lebih rendah. Ini bukan aturan universal: hanya ketika semanticScore dari batch hasil lebih tinggi daripada keywordScore-nya, penurunan bobot akan menurunkan skor total; jika tidak, justru meningkatkannya. Jika min_score tidak diturunkan secara bersamaan, bahkan hasil yang cocok secara semantik akan difilter:
Kuerisemantic_weight=0.15semantic_weight=0.7
/api/v2/orders/{orderId}8 hasil, skor tertinggi 0.2698 hasil, skor tertinggi 0.602
kubectl -n order rollout undo deploy/order-api4 hasil8 hasil
Kueri bahasa alami "Mengapa API order belakangan ini melambat secara signifikan?"3 hasil8 hasil

Saat Anda menggunakan semantic_weight=0.15, atur min_score menjadi sekitar 0.05 (contoh di atas dikonfigurasi demikian). Jika Anda membiarkan min_score pada 0.15 atau lebih tinggi, recall untuk kueri berbasis perintah dan kueri bahasa alami turun lebih dari separuhnya. Saat menyesuaikan, tetapkan satu parameter dan amati kedua sub-skor melalui scoreDetails sebelum memutuskan.

Batasi perintah berisiko tinggi dan hasil kosong

Asisten troubleshooting mengeluarkan perintah yang dapat dieksekusi secara langsung, sehingga dua hal harus dibatasi.

Perintah berisiko tinggi. Tandai tingkat risiko dan persyaratan konfirmasi dalam tabel di dalam file sumber, dan model akan meneruskannya secara akurat. Dalam pengujian kami, perintah restart yang ditandai "risiko tinggi, konfirmasi dua orang diperlukan" dalam Runbook, saat ditanyakan, dikembalikan oleh model bersama perintah tersebut ditambah pernyataan eksplisit "tingkat risiko tinggi", "konfirmasi dua orang diperlukan", dan "jangan lewati troubleshooting dan jalankan restart secara langsung".

Hasil pengambilan kosong. Kode harus mengintersepsi kasus ini, seperti dijelaskan di Langkah 4: Adaptasi kode yang digunakan kembali.

Langkah 4: Adaptasi kode yang digunakan kembali

Proyek yang digunakan kembali memerlukan dua modifikasi sebelum Anda memverifikasi asisten: fallback hasil kosong di app.py, dan perbaikan kode kembalian di kb_client.py.

Intersepsi hasil pengambilan kosong di app.py

Dalam app.py yang digunakan kembali, fungsi llm_answer() tetap memanggil LLM meskipun hasil pengambilan kosong. Pada titik itu konteksnya adalah string kosong, dan model menjawab sepenuhnya berdasarkan pengetahuannya sendiri. Dalam pengujian kami, saat kami bertanya "Bagaimana cara memulihkan cluster Redis split-brain?", yang tidak tercakup dalam basis pengetahuan, model menghasilkan rencana operasi lengkap dengan parameter dan sama sekali tidak memberikan peringatan. Dalam skenario troubleshooting, pengguna mungkin menyalin perintah tersebut dan menjalankannya langsung di lingkungan produksi, sehingga hal ini harus diintersepsi di tingkat kode:

def llm_answer(question: str, results: list[dict[str, Any]]) -> str:
    if not LLM.get("enabled", True):
        return "The LLM is not enabled. Review the retrieval results below."
    if not results:
        return "No relevant document was retrieved from the knowledge base, so no troubleshooting steps can be provided. Do not perform any change operation based on this. We recommend that you contact the module owner."
    ...

Membatasi hal ini hanya melalui prompt tidak dapat diandalkan — bahkan jika Anda menyatakan "beri tahu secara eksplisit ketika materi tidak mencakup pertanyaan", model tetap memberikan jawaban.

Kriteria penerimaan terakhir di Langkah 5: Unggah, publikasikan, dan verifikasi mencakup modifikasi ini.

Perbaiki pemeriksaan kode kembalian di kb_client.py

Dalam kb_client.py yang digunakan kembali, fungsi _check() mengevaluasi getattr(body, "code", 0) != 0. Nilai code dari respons sukses adalah None, sehingga pengambilan sukses dilaporkan sebagai "Failed: None". Ubah pemeriksaan menjadi getattr(body, "code", None) not in (None, 0, "0"). Setelah perbaikan, pengambilan sukses tidak lagi melaporkan "Failed: None".

Langkah 5: Unggah, publikasikan, dan verifikasi

  1. Unggah file sumber. MetaFields berlaku untuk seluruh batch; skrip terlebih dahulu mengelompokkan berdasarkan tag lalu mengirimkan secara batch.

    python upload.py --manifest documents.jsonl
  2. Di halaman Data Management Konsol, pastikan status file sumber adalah Completed. Respons sukses dari API unggah hanya berarti parsing asinkron telah diajukan.

  3. Di halaman Version Management, klik Publish Version. Setelah menyelesaikan wizard, pastikan status versi baru adalah Published.

    Penting

    Paling banyak 3 versi yang dipublikasikan dapat ada secara bersamaan. Setelah batas tercapai, tombol Publish Version akan dinonaktifkan, tetapi halaman tetap menampilkan "Saat ini terdapat N perubahan yang menunggu untuk dipublikasikan". Hapus versi lama yang tidak lagi diperlukan dari catatan versi terlebih dahulu. Dokumen pengembangan sering berubah (setiap rilis mungkin memperbarui referensi API dan Runbook), jadi simpan hanya "versi saat ini + versi historis terbaru".

  4. Jalankan layanan:

    python app.py
  5. Kirim pertanyaan uji:

    curl -sS http://127.0.0.1:7860/api/ask \
      -H 'Content-Type: application/json' \
      -d '{"question":"In what order should I troubleshoot a connection timeout?"}'
  6. Verifikasi terhadap lima kriteria penerimaan berikut:

    • Halaman terbuka secara normal, dan setelah Anda mengirim pertanyaan, jawaban beserta sumber pengambilan dikembalikan bersamaan.

    • Setiap [Source N] dalam jawaban dapat dicocokkan dengan chunk file sumber yang sesuai di bagian sumber di bawahnya.

    • Saat Anda menanyakan kode kesalahan lengkap, semua file sumber tempat kode kesalahan tersebut muncul akan tercantum. Dalam pengujian kami, kueri ORD-50021 berhasil mencantumkan empat file sumber — tabel kode kesalahan, referensi API, Runbook, dan postmortem — lengkap dengan lokasi masing-masing.

    • Saat Anda menanyakan operasi berisiko, jawaban mencakup tingkat risiko dan persyaratan konfirmasi manual.

    • Saat Anda menanyakan sesuatu yang tidak tercakup dalam basis pengetahuan, responsnya adalah "materi tidak mencukupi" dengan peringatan untuk tidak melakukan operasi perubahan apa pun, dan tidak ada perintah fiktif yang muncul. Uji kasus ini secara praktis.

Catatan untuk skenario pengembangan

  • Titik masuk per modul — Setelah tag_filter mengunci module, titik masuk hanya menjawab pertanyaan tentang modul tersebut. Pertahankan juga pertanyaan contoh dalam modul yang sama.

  • Istilah eksak lengkap — Pertahankan kode kesalahan lengkap, path API, perintah, dan nomor versi dalam file sumber. Istilah eksak ini merupakan titik masuk utama pengambilan dalam skenario ini.

  • Penandaan risiko — Tandai tingkat risiko dan persyaratan konfirmasi dalam file sumber. Jangan mengandalkan model untuk menilai perintah mana yang berbahaya.

  • Tidak ada rahasia dalam unggahan — Jangan unggah rahasia, token, akun jaringan internal, atau string koneksi database produksi. Konten chunk dikirim ke LLM sebagai konteks.

  • Deskripsi API yang tidak digunakan lagi — Pertahankan deskripsi operasi API yang deprecated. Dalam pengujian kami, setelah referensi API menyatakan "API v1 sudah tidak digunakan dan nama parameternya tidak kompatibel", model tidak mencampurkan parameter lama saat menjawab pertanyaan tentang parameter API baru.

  • Bidang tags dalam hasil pengambilan tidak mencerminkan modul dan versi yang ditulis. Ini adalah bidang yang berbeda dari MetaFields pada AddDocuments, dan tidak ada parameter yang dapat mengaktifkan pengembaliannya. Nilai kosong tidak berarti unggahan gagal. Saat Anda perlu menganotasi modul dan versi dalam jawaban, gabungkan hasil pengambilan dengan documents.jsonl berdasarkan documentId dan tambahkan informasi tersebut ke konteks.

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

FAQ

GejalaPenyebab dan solusi
Pertanyaan mengembalikan 500, dan log menunjukkan 400 Unsupported tag filter operatorop menggunakan alias seperti eq, ==, atau like. Gunakan =, in, atau not in sebagai gantinya.
Filter tag ditambahkan, tetapi jumlah hasil persis sama seperti tanpa filterOperator yang tidak efektif (seperti >, , , atau empty) digunakan. Hanya =, in, dan not in yang berlaku.
API dengan nama identik dari sistem lain diambilFilter module tidak dikonfigurasi, atau nilai filter tidak sesuai dengan nilai yang ditulis saat unggah.
Jumlah hasil pengambilan jauh lebih sedikit dari yang diharapkanSaat semantic_weight rendah, skor keseluruhan ditekan ke bawah, dan dikombinasikan dengan min_score, lebih banyak hasil difilter. Turunkan min_score seperti dijelaskan di Sesuaikan semantic_weight dan min_score bersama.
Pengambilan kode kesalahan tidak akuratPastikan enable_query_expansion bernilai false. Saat diaktifkan, kode kesalahan mungkin ditulis ulang.
Filter tag selalu mengembalikan 0 hasilEjaan nama tag tidak sesuai dengan yang ditulis saat unggah (API tidak melaporkan kesalahan dan hanya mengembalikan 0 hasil). Verifikasi di halaman detail basis pengetahuan dengan memilih Tags > Manage.
Pertanyaan yang tidak tercakup dalam basis pengetahuan mengembalikan perintah yang tampaknya dapat dieksekusillm_answer() tetap memanggil LLM saat hasil pengambilan kosong. Tambahkan fallback hasil kosong seperti dijelaskan di Langkah 4: Adaptasi kode yang digunakan kembali.
Detail dalam file sumber HTML tidak dapat diambilHTML memiliki granularitas chunk yang lebih kasar. Turunkan panjang segmen maksimum. Konversikan HTML yang berisi banyak kode ke Markdown terlebih dahulu.
Pengambilan melaporkan "Failed: None"Pemeriksaan di _check() pada kode yang digunakan kembali salah (getattr(body, "code", 0) != 0); nilai code dari respons sukses adalah None. Terapkan perbaikan di Langkah 4: Adaptasi kode yang digunakan kembali.
Pengambilan mengembalikan 404 Knowledge base version ... does not existBelum ada versi yang dipublikasikan, atau nomor versi yang dikode keras dalam konfigurasi telah dihapus. Gunakan LATEST_PUBLISHED sebagai gantinya.

Langkah selanjutnya

  • Perluas cakupan modul demi modul: buat titik masuk independen untuk setiap nilai module, dan pertahankan pertanyaan contoh dalam modul yang sama.

  • Bersiap untuk produksi: beralih dari server pengembangan Flask ke server WSGI produksi, dan tambahkan manajemen rahasia, otentikasi, audit, dan Pembatasan laju.

  • Kelola versi seiring perubahan dokumen Anda: publikasikan versi baru saat referensi API atau Runbook diperbarui, dan simpan hanya versi saat ini plus versi historis terbaru.