2 poin oleh GN⁺ 2024-12-09 | 1 komentar | Bagikan ke WhatsApp
  • Respons model lokal kini bisa dibatasi agar sesuai dengan JSON Schema, sehingga beban parsing pascapemrosesan berkurang dan hasil ekstraksi data menjadi lebih konsisten
  • Pengguna dapat meminta output terstruktur dengan cara yang sama di cURL, Python, dan JavaScript dengan mengirimkan skema ke parameter format
  • Di Python, penggunaan Pydantic, dan di JavaScript, Zod, memudahkan penghubungan definisi skema dan validasi respons di level kode
  • Contohnya mencakup pengembalian dan validasi informasi negara, teks tentang hewan peliharaan, serta hasil analisis gambar llama3.2-vision ke dalam field JSON yang telah ditentukan
  • Jika membutuhkan hasil yang stabil, disarankan menambahkan “return as JSON” ke prompt dan menurunkan temperature ke 0

Membatasi respons model dengan JSON Schema

  • Ollama mendukung output terstruktur yang membatasi hasil model agar mengikuti format JSON Schema tertentu
  • Library Ollama untuk Python dan JavaScript juga telah diperbarui untuk mendukung output terstruktur
  • Fitur ini dapat digunakan untuk tugas-tugas berikut
    • Mem-parsing data dari dokumen
    • Mengekstrak data dari gambar
    • Menstrukturkan respons model bahasa
    • Mendapatkan keandalan dan konsistensi yang lebih tinggi dibanding JSON mode

Instalasi dan cara pemanggilan

  • Anda perlu mengunduh versi terbaru Ollama
  • Library Python dapat diperbarui ke versi terbaru dengan perintah berikut
pip install -U ollama
  • Library JavaScript dapat diinstal dengan perintah berikut
npm i ollama
  • Saat meminta output terstruktur, kirimkan skema ke parameter format pada permintaan cURL atau library Python/JavaScript

Mengirim JSON Schema dengan cURL

  • Contoh cURL mengirim permintaan ke http://localhost:11434/api/chat, dengan model disetel ke llama3.1 dan stream ke false
  • Pada format, masukkan skema objek yang memiliki name, capital, dan languages
    • name: string
    • capital: string
    • languages: array string
    • Ketiga field ditandai sebagai required
  • Respons akan dikembalikan dalam format JSON Schema yang disertakan dalam permintaan
{
  "capital": "Ottawa",
  "languages": [
    "English",
    "French"
  ],
  "name": "Canada"
}

Menggunakan library Python dan JavaScript

  • Python

    • Ollama Python library mengirimkan skema sebagai objek JSON ke parameter format
    • Skema dapat diteruskan sebagai dict, dan cara yang direkomendasikan adalah melakukan serialisasi dengan model_json_schema() dari Pydantic
    • Contohnya mendefinisikan model Country dengan field name, capital, dan languages, lalu memvalidasi respons dengan Country.model_validate_json()
country = Country.model_validate_json(response.message.content)
  • Output contoh mengembalikan Canada, Ottawa, English, dan French sesuai field yang telah didefinisikan
  • JavaScript

    • Ollama JavaScript library mengirimkan skema sebagai objek JSON ke parameter format
    • Skema dapat diteruskan sebagai object, dan cara yang direkomendasikan adalah menggunakan Zod bersama zodToJsonSchema()
    • Contohnya mendefinisikan skema Country sebagai objek Zod, lalu mem-parsing body respons dengan JSON.parse() dan memvalidasinya dengan Country.parse()
const country = Country.parse(JSON.parse(response.message.content));

Mengekstrak data dari teks dan gambar

  • Ekstraksi teks hewan peliharaan

    • Output terstruktur dapat digunakan untuk mengambil informasi yang dibutuhkan dari teks
    • Contohnya mendefinisikan model Pydantic Pet dan PetList untuk mengembalikan informasi hewan peliharaan dalam struktur JSON
      • Pet: name, animal, age, color, favorite_toy
      • PetList: array pets
    • Teks masukan berisi informasi tentang dua ekor kucing
      • Luna: usia 5 tahun, bulu abu-abu, menyukai yarn
      • Loki: usia 2 tahun, berwarna hitam, menyukai tennis balls
    • Output divalidasi sebagai daftar objek Pet sesuai skema yang didefinisikan
  • Deskripsi gambar dengan model vision

    • Output terstruktur dapat digunakan bersama model vision
    • Contohnya menganalisis gambar dengan llama3.2-vision dan mengembalikan hasil yang sesuai dengan skema ImageDescription
    • Skema tersebut mencakup field berikut
      • summary
      • objects
      • scene
      • colors
      • time_of_day
      • setting
      • text_content
    • Contoh permintaan menginstruksikan analisis objek, adegan, warna, dan teks yang dapat dideteksi dari gambar
    • Pada opsi, temperature disetel ke 0 untuk menghasilkan output yang lebih deterministik
    • Output contoh merangkum pemandangan pantai dengan pohon palem, lalu mengembalikan objek tree dan beach, warna, waktu, serta pengaturan luar ruang dalam field terstruktur

Menggunakan API yang kompatibel dengan OpenAI

  • Contoh yang kompatibel dengan OpenAI mengatur klien OpenAI dengan base_url="http://localhost:11434/v1"; dan api_key="ollama"
  • Gunakan client.beta.chat.completions.parse() untuk mengirim model Pydantic PetList ke response_format
  • Pada respons, periksa completion.choices[0].message, dan jika ada parsed, tampilkan hasil yang telah diparse
  • Jika ada refusal, tampilkan respons penolakan, dan openai.LengthFinishReasonError ditangani sebagai kasus ketika token terlalu banyak

Pengaturan output stabil dan rencana ke depan

  • Untuk mendefinisikan skema respons, disarankan menggunakan Pydantic di Python atau Zod di JavaScript
  • Menambahkan “return as JSON” ke prompt dianjurkan agar model memahami permintaan
  • Jika menginginkan output yang lebih deterministik, setel temperature ke 0
  • Rencana ke depan mencakup hal-hal berikut
    • Eksposur logits untuk controlled generation
    • Peningkatan performa dan akurasi output terstruktur
    • Akselerasi GPU untuk sampling
    • Dukungan format tambahan di luar JSON Schema

1 komentar

 
GN⁺ 2024-12-09
Komentar Hacker News
  • Jika memerlukan pembatasan output yang lebih kuat, llama.cpp mendukung GBNF
    https://github.com/ggerganov/llama.cpp/blob/master/grammars/...

    • Sepertinya memang menggunakan itu
    • Saya penasaran apakah kualitas output untuk tata bahasa arbitrer memuaskan
      Sekilas rasanya model kemungkinan membuat JSON lebih baik daripada format lain karena jauh lebih sering melihat JSON
    • Saya penasaran dalam hal apa ini lebih kuat
  • Ini kabar baik
    Saat membuat data CSV, saya sempat memikirkan bagaimana menyusun prompt umum tanpa frasa yang tidak perlu seperti "Here is your data" atau "Please note blah blah" di awal atau akhir, jadi senang karena sekarang kita bisa mendefinisikan format pengembalian yang diinginkan secara tepat dan langsung mengirim structured output ke CSV

    • Meski begitu, Anda tetap perlu memasukkan instruksi untuk menghasilkan CSV agar prompt berada dalam konteks yang benar
      Jika tidak, hasilnya mungkin secara teknis berbentuk CSV tetapi tidak bermakna. Model sebenarnya mungkin sedang mencoba menulis jawaban berbentuk paragraf, tetapi token sampler memilih token berprobabilitas rendah yang sebenarnya tidak terlalu ingin dikeluarkan model
    • Dalam banyak kasus, masalah seperti ini bisa dicegah dengan mengisi awal output terlebih dulu dengan \n dan membuatnya berhenti di
  • Berfungsi. Saya memasukkan kalimat berikut ke gemma2:2b dan JSON yang diinginkan keluar
    You have spent 190 at Fresh Mart. Current balance: 5098
    Hasilnya adalah {"amount": 190, "balance": 5098, "category": "Shopping", "place": "Fresh Mart"}

    • JSON-nya memang cukup tidak konsisten, tetapi untuk model yang sangat kecil, apalagi gemma, itu masih masuk akal
  • Benar-benar mengesankan. Ini memang salah satu fitur yang saya inginkan
    Alasan ollama bagus adalah karena ia memberi kesan LLM bisa dipakai seperti program UNIX lain, dan membuat LLM terasa cocok secara alami di lingkungan UNIX
    Tapi saya penasaran apakah ada yang sudah berhasil menjalankannya dengan baik di AMD GPU. Katanya lebih sulit, tetapi saya ingin mendukung kompetitor saat membeli kartu tahun depan

    • Bisa. Bahkan GPU bawaan pun bisa
      Saya mengalokasikan 16GB shared memory lewat BIOS pada mini PC dengan 780M, dan hasilnya berjalan cukup baik
  • Saya penasaran dampak pembatasan seperti ini terhadap kualitas output LLM
    Dalam beberapa kasus, kalau kualitas output lebih tinggi, saya mungkin akan memilih mem-parsing Markdown atau teks biasa

    • Saat memakai model OpenAI, strategi dua kali lewat sangat bagus jika Anda bisa menanggung biaya token tambahan
      Pertama, gunakan model yang lebih berat dan bahasa alami untuk menangani penalaran dalam bagian-bagian Markdown serta memberikan jawaban akhir dalam bahasa alami. Jika memungkinkan, beri label yang jelas dengan header Markdown
      Kedua, gunakan model yang lebih murah dan cepat untuk mengubah jawaban itu menjadi format structured output, agar bisa dikonsumsi oleh bagian pipeline yang non-LLM
      Pada dasarnya ini membuat batas yang rapi di sekitar bagian bahasa alami yang ambigu dengan mode JSON schema, dan membuat LLM berperan sebagai preprocessor yang menangkap outputnya sendiri ke dalam format yang berguna
    • Itu bergantung pada seberapa jauh model di-fine-tune untuk output JSON
      Anda juga perlu memberi tahu model tentang skemanya. Jika tidak, masalah tokenisasi aneh akan lebih sering muncul
      Misalnya, jika skema mengharapkan key JSON "foobarbaz" dan tokenisasi BPE standar adalah ["foobar", "baz"], maka token mask yang dibuat library constrained output saat ini bisa mengizinkan model memilih di antara "f", "foo", "foobar". Jika model memilih "foo", constraint lalu memaksa token berikutnya misalnya "bar" dan "baz". Akibatnya model melihat ["foo", "bar", "baz"], bukan ["foobar", "baz"], dan itu membingungkan [0]
      Jika prompt memberi tahu model bahwa "foobarbaz" adalah salah satu key dalam skema, model biasanya akan lebih memilih "foobar" daripada "foo"
      [0] Pada model terbaru, token-token itu memang saling terkait karena normalisasi, tetapi tidak identik
    • Tergantung situasinya, tetapi dari sisi penalaran memang ada dampak negatif, dan dalam kebanyakan kasus perbedaannya tidak terlalu besar
      Ini sangat bergantung pada apakah LLM dan prompt-nya memang sejak awal cukup mungkin menghasilkan respons JSON. Makin keras Anda memaksa arah LLM, makin kecil kemungkinan ia menghasilkan input yang normal
      Pada model kecil, Anda lebih cepat mencapai tepi ruang yang masih punya daya prediksi bermakna, lalu output mulai mendekati noise acak
      Ini bukan pengukuran yang ketat, hanya kesan setelah menghabiskan banyak waktu di berbagai proyek LLM. Saya belum mencoba alat khusus ini, tetapi ollama sebelumnya juga bisa menjamin output JSON dengan teknik yang tampaknya mirip, dan saya pernah mengerjakan sesuatu yang mirip jsonformer untuk oobabooga, runtime tool LLM lain, bersama seorang rekan
    • Saya terus mengikuti riset terkait. Saya sedang melihat cara meningkatkan sampling secara umum, baik dari sisi kecepatan maupun akurasi
      Semoga jika perubahan seperti itu masuk, generasi terstruktur yang umum dan tidak terbatas pada JSON juga bisa menjadi mungkin
    • Bisa jadi saya sepenuhnya salah soal kegunaan alat seperti instructor
      Memang mudah menghabiskan banyak token, tetapi jika pekerjaan yang ingin dilakukan memang layak dengan biayanya, ini bisa didorong cukup jauh. Mungkin bukan kualitas absolut terbaik, tetapi alat yang bisa memberi level 95% tanpa banyak usaha tetap layak ada di kotak peralatan
  • Saya penasaran apakah ini bisa dipakai pada model apa pun yang didukung
    Di hardware saya, hanya model 1B~3B yang bisa berjalan stabil, jadi saya bertanya

    • Saya penulis postingan blog itu. Seharusnya bisa dipakai dengan model apa pun
      Pada model kecil hasilnya mungkin naik turun, tetapi meminta "kembalikan x sebagai JSON" cenderung membantu akurasi
  • PR untuk fitur ini sempat terbuka hampir 1 tahun
    Agak disayangkan para maintainer terlalu diam

    • Saya penulis tulisan ini sekaligus salah satu maintainer. Saya setuju. Para maintainer lambat merespons, dan secara umum saya ingin mendorong lebih banyak kontribusi
      Saya berharap tahun depan bisa lebih baik dalam meninjau dan me-merge PR komunitas
    • Dari nuansanya, kelihatannya arahnya makin company-centric, jadi semuanya dilihat lewat lensa itu dan dari sudut pandang memaksimalkan profit
    • Saya juga ingin ikut berkolaborasi membangun ini, tetapi percakapannya mendadak terputus
  • Masih pakai oobabooga. Berkat dukungan exlv2, inferensi jadi jauh lebih efisien di dual 3090

    • Sudah agak lama tidak menyentuh ooba, jadi penasaran bagaimana kondisi exl2 dan skema kuantisasi non-homogen seperti q3k_s saat ini
      Kalau tidak salah, exl2 memang lebih cepat, tetapi terutama pada kedalaman bit rendah, kuantisasi gptq tampaknya dulu lebih baik dari sisi akurasi
  • Penasaran nilai tambah apa yang ada dibandingkan outlines
    https://www.souzatharsis.com/tamingLLMs/notebooks/structured...

    • Saya penulis blog tersebut. Implementasi saat ini bisa dibuat dengan cepat menggunakan llama.cpp GBNF. Nilai tambah terbesar saat ini adalah bahwa fitur ini sudah dirilis
      Berdasarkan riset terbaru terkait outlines/xgrammar, saya berharap bisa memperbarui sampling agar mendukung lebih banyak format, meningkatkan akurasi, dan memperbaiki performa
  • Penasaran apakah ada cara terbaik untuk memberikan input terstruktur ke LLM
    Misalnya, memasukkan 100 kalimat lalu meminta model mengklasifikasikan masing-masing dengan beberapa cara. Menerima data terstruktur itu mudah, tetapi cara saya menambahkan nomor baris di depan terasa agak kasar

    • Model dilatih dengan Markdown, JSON, dan berbagai bahasa pemrograman, jadi salah satu dari itu seharusnya bisa digunakan
      Namun dalam kasus ini, yang terbaik adalah memberikan kalimat satu per satu agar model tidak bingung
      Jika prompt disusun dalam bentuk "Klasifikasikan kalimat berikut. Aturannya adalah ..." + kalimat, Anda bisa memanfaatkan cache prefiks, sehingga performanya bahkan bisa lebih baik daripada menanyakannya sekaligus
      Tentu saja, ini hanya memungkinkan jika ada cache prefiks dan Anda tidak dikenai biaya per token input. Saat ini sebagian besar penyedia memungkinkan penggunaan dengan biaya lebih rendah jika Anda menyatakan ingin memakai cache prefiks