1 puan yazan GN⁺ 2023-08-15 | 1 yorum | WhatsApp'ta paylaş
  • Outlines, LLM’ler için bir yapılandırılmış çıktı aracıdır; üretim sırasında istenen çıktı türünü belirterek verinin ilgili yapıyla tam olarak eşleşmesini garanti eder
  • Üretimden sonra hatalı çıktıları ayrıştırma, regex veya kırılgan kodlarla düzeltmek yerine, üretim aşamasında geçerli yapıyı doğrudan zorunlu kılar
  • Kullanım biçimi model(prompt, output_type) şeklindedir; Literal["Yes", "No"], int, Pydantic model gibi Python tip sistemiyle uyumlu çıktı tanımları yapılabilir
  • Desteklenen çıktı türleri: önceden tanımlı seçenekler, fonksiyon imzası tabanlı Function Calls, JSON/Pydantic şemaları, regex kalıpları ve grammar tabanlı yapı zorlamadır
  • Model entegrasyonları; sunucu destekli vLLM·Ollama, yerel model destekli transformers·llama.cpp ve API destekli OpenAI·Gemini·Dottxt olarak ayrılır
  • Örnek iş akışları; müşteri e-postasını servis biletine dönüştürme, ürün açıklamasını kategori verisine dönüştürme, eksik etkinlik açıklamasından yapılandırılmış bilgi veya "I don't know" döndürme, belgeleri önceden tanımlı kategorilere sınıflandırma ve doğal dille yazılmış toplantı isteğini fonksiyon parametrelerine dönüştürme şeklindedir
  • Prompt şablonları Jinja tabanlı outlines.Template.from_string ve dosyadan yüklemeyi destekler; karmaşık prompt’ları koddan ayırıp yeniden kullanmak içindir
  • Kurulum pip install outlines ile yapılır; .txt API şu anda early access durumunda gösterilmektedir

1 yorum

 
GN⁺ 2023-08-15
Hacker News görüşleri
  • Bu kütüphane, mekanizma olarak sözlük uzayının bir kısmını maskeleme ve zaman adımlarında verimli biçimde ilerleme şeklinde basit bir fikir kullanıyor gibi görünüyor; harika.
    Ancak temel bir LLM’in çıktısına yapı giydiren kütüphaneleri kullanmış biri olarak, Llama2 gibi temel modellerin gerçekten iyi çalışıp çalışmadığını merak ediyorum.
    Benim deneyimime göre yanıt “hiç de değil”e yakın; gerçekten çalışır hâle getirmek için belirli kullanım amacına yönelik epey talimat ayarı gerekiyordu.
    Üstelik talimat ayarlı bir modelde üretim sırasında sonradan durum uzayını maskelemek, sonuçta üretim dağılımını değiştirmek anlamına geliyor; bunun talimat ayarına zarar verebileceği sezgisel olarak ters görünüyor.

    • Özellikle ham llama-2 kullanmak için iyi bir neden göremiyorum. HF Hub’da llama-2’nin talimatla ince ayarlanmış çok güçlü sürümleri var ve bunlar işi çok daha iyi yapacaktır. Örneğin Stability-AI’nin Beluga-2’si: https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderb...
      İkinci noktaya gelince; hedef, örneğin modelin yalnızca JSON üretmesini sağlamaksa, hangi çıktı token’larının kullanılabileceğini ve kullanılamayacağını sınırlayarak bunu %100 yapmak mümkün.
    • Llama 2 13B beni epey etkiledi; kullandıkça yerel LLM oyuncağından öte gerçekten işe yarayabileceğini düşünmeye başladım.
      M2 Mac’te GPU kullanabildiğim için MLC sürümünü https://github.com/simonw/llm-mlc eklentisiyle kullanıyorum.
    • En azından kod üretiminde, token düzeyinde üretimi yönlendirmek temel modelleri de ciddi biçimde iyileştirebildi.
      “Guiding Language Models of Code with Global Context using Monitors” makalesinde (https://arxiv.org/abs/2306.10763) Monitor Guided Decoding öneriliyor; LLM’i statik analizle bağlayarak tip açısından tutarlı kod üretmeye yönlendiriyor.
      Hiçbir ince ayar yapmadan, belirli noktalarda statik analizle token düzeyinde üretimi yönlendirmek, üretilen kodun kalitesini hem derlenebilirlik hem de doğru cevapla uyum açısından büyük ölçüde artırdı. Çok küçük bir model (1.1B) bile çok daha büyük bir modelden (175B) daha fazla derlenebilir kod üretirken doğru cevapla uyumu da iyileştirdi.
    • “Talimat ayarlı bir modelde üretim sırasında sonradan maskelemenin üretim dağılımını değiştirmesi” deniyorsa, bunun test güdümlü geliştirmede yaptığımız şeyden farkı ne, diye düşünüyorum.
      Başlıca fark, üretim fonksiyonunun LLM değil insan olmasıydı. Aradaki insanı çıkarmamak için bir neden göremiyorum.
    • Talimat ayarının kendisi görece “önemsiz” sayılır; asıl zor olan sınır koşullarını ele almak.
      Geleneksel kodda sınır koşulları kelimenin tam anlamıyla küçük özel durumlara daha yakındı; LLM’lerde ise neyin modeli saçma bir yöne savuracağını bilemiyorsunuz ve ayrıştırma kodunun bu kaosu kaldırması gerekiyor.
      Başka bir deyişle, sınır koşulu olarak ele alınması gereken durumların oranı dramatik biçimde artmış gibi.
  • GPT-4, sistem mesajına yalnızca örnekler koysanız bile geçerli JSON döndürebiliyor ve on denemenin dokuzunda çalışıyor.
    Ama hâlâ olasılıksal ve on denemenin dokuzu yeterli değil.
    Bazen {"key1": "value1", "key2": "value2" for i in range(n)} gibi halüsinasyonlu yanıtlar da üretebiliyor.
    Ayrıştırma hata mesajıyla birlikte tekrar prompt verdiğinizde genelde ikinci denemede çözülüyor.
    Ancak çift tırnakları ve satır sonu karakterlerini escape etmek daha az kararlı. Birkaç örnek verseniz bile yaklaşık yarısını doğru escape ediyor; escape hatasını yeniden prompt etseniz de başarı oranı yaklaşık %50’de kalıyor.

    • Hata olduğunda yeniden prompt etme yaklaşımını Microsoft’un yeni kütüphanesi TypeChat de kullanıyor: https://github.com/microsoft/TypeChat
      İlgili prompt burada: https://github.com/microsoft/TypeChat/blob/c45460f4030938da3...
      Burada görülen dilbilgisi tabanlı yaklaşımın veya https://github.com/ggerganov/llama.cpp/pull/1773 benzeri yöntemlerin çok daha zarif çözümler olduğunu düşünüyorum.
    • JSON yerine XML çıktısı istemek daha iyi sonuç verdi. (1) XML, gerçek dil ve anlamdan daha fazlasını taşıyabiliyor ve LLM’ler bunu seviyor; (2) ayrıştırıcıyı daha hoşgörülü yapabiliyorsunuz.
      İnsanların JSON istemesini anlıyorum ama bana göre bu, bir kediyi yüzdürmeye çalışmaya benziyor. Sonunda başarmak mümkün olsa da doğal eğilim bu değil.
    • ChatGPT’nin function calling özelliğini kullanınca, prompt’ta hata yapmadığım sürece GPT-4’ten %100 geçerli JSON alıyorum.
      Başlıca hata, bir kaçış yolu sunmamak. LLM doğru yanıtı bulmaya çalıştığı için, metinleri verip yapılandırılmış veri döndürmesini istediğinizde metinlerden biri boşsa doğru cevabı belirlemek zorlaşıyor ve halüsinasyon oluşuyor.
      Çözüm, argümanlardan biri olarak textIsMissing gibi bir boolean koymak şeklinde bir kaçış yolu oluşturmak. Bu tür hata biçimlerini hesaba katarsanız kusursuz çalışıyor.
    • GPT-4’ten, örnek PHP kodunu rastgele bir JSON’un içine koyup döndürmesini istedim; daha ilk denemede JSON linter’dan geçemedi.
      Birkaç kez tekrar denedim ve ardından düzeltme de yaptırdım ama doğrulamadan geçemedi; %100 geçerli JSON’u bir kez bile üretemeyince sonunda vazgeçtim.
    • Dilbilgisi kısıtlı üretimin iki büyük avantajı var.
      Birincisi, prompt’a çok fazla örnek koymanız gerekmediği için daha az token kullanıyor.
      İkincisi, unutma probleminden daha az etkileniyor.
      Küçük bir avantaj olarak, istediğiniz çıktının nerede başlaması gerektiğini tam olarak kontrol edebiliyorsunuz. Yine de genel olarak bunu güzel bir ek özellik olarak görüyorum; çok temel bir şey olduğunu düşünmüyorum.
  • LLM’lerin gücünün büyük bir kısmı, yanıtlarındaki kalibre edilmiş olasılık dağılımından geliyor; bu teknik muhtemelen o yeteneği çöpe atıyor gibi. Bunun neden yeterli sayıldığını merak ediyorum.
    Basit bir örnek olarak, LLM’in olası çıktılarının yalnızca “hello world”, “food”, “hello”, “good day” olduğunu ve prompt yokken hepsinin eşit olasılıklı olduğunu varsayalım. Gramerin de yalnızca çıktının bir yerinde boşluk olması kısıtını koyduğunu kabul edelim.
    Gramerden geçene kadar LLM çıktısını örneklersek “hello world” ve “good day” aynı olasılıkla gelir. Ama web sitesindeki tekniği uygularsak “hello world”, “good day”den iki kat daha sık çıkar.
    Temel sorun şu: Belirli bir yanıt önekinin geçerli bir yanıta yol açma olasılığı son derece düşük olabilir; buna rağmen bu teknik, başarılı olacağını varsayarsak, o önekten geçerli bir yanıt üretir. Uygun noktalarda yeterince bağımsızlık varsa sorun olmayabilir; ama otoregresif modellerde ilişkili hatalar hızla birikir.
    Yalnızca JSON özelinde sorarsak: LLM şemaya uymayan yanıtlar üretirken olgusal hataları, halüsinasyonları, kesilmiş dizeleri, önemli karakterleri atlamayı vb. daha mı çok yapar, daha mı az? Olgusal hata oranı şema hata oranıyla önemsiz olmayan bir şekilde ilişkiliyse bu yol göründüğünden daha tehlikeli. Belirli sözcüklerin ya da bitişik kalmış sözcük öbeklerinin LLM çıktısı üzerinde büyük etkiler yaratabildiğini görünce, şema uyumluluğu gibi ayrıntıların da çıktının başka özelliklerine yayılma olasılığı yüksek görünüyor.

    • Bu durumdaki gibi çoktan seçmeli üretim söz konusuysa, olası çıktılardan biri regex’e uymadığında onu üretimden çıkarmak yeterli.
      “Yanıt önekinin geçerli yanıta yol açma olasılığı çok düşüktü ama teknik bir şekilde geçerli yanıt kurup sorun çıkarıyor” türünden bir örnek düşünmeye çalıştım, fakat aklıma pek gelmedi. İyi bir örnek varsa bu ilginç bir araştırma sorusu olabilir.
  • Bununla ilgili olarak LLama.cpp geçen ay gramer tabanlı örneklemeyi hayata geçirdi.
    https://news.ycombinator.com/item?id=36819906
    https://github.com/ggerganov/llama.cpp/pull/1773

    • Yukarıdaki makalede açıklandığı gibi bizim yaklaşımımız da gramer tabanlı örneklemeye genişletilebilir. İlgili PR: https://github.com/normal-computing/outlines/pull/178
      Bizim yöntemimiz çok daha verimli. llama.cpp her adımda maske oluşturmak için tüm sözlüğü, yaklaşık 50 bin token’ı dolaşıyor.
      Biz başlangıçta bir indeks oluşturuyoruz; her adımda maskeyi kurarken yalnızca sözlük araması yapmak yeterli oluyor. Bu, hızı bellekle takas eden bir yaklaşım ve örnekleme standart örnekleme kadar hızlı.
    • Benzer bir dönemde bizim de gramer güdümlü yönlendirme uygulamamız vardı: https://github.com/normal-computing/outlines/pull/131
      Konuyla ilgili çok sayıda makale olduğu düşünülürse başka yerlerde de birkaç tane daha olmuş olmalı. Buradaki ve mevcut çalışmadaki ana fikir, çok düşük maliyetli yönlendirme sağlamak; regex örneğinde bir süredir uygulanmış durumdaydı ve sonrasında JSON’a genişletildi.
  • Böyle bir şey yaptığınız için teşekkürler; çalışma prensibi o kadar bariz bir fikir ki birinci sınıf platformların bunu hâlâ yapmıyor olması şaşırtıcı.
    JSON dışında yapılandırılmış girdi gerektiren başka işlerde nasıl kullanılabileceğini merak ediyorum.

    • LLM teknolojisinin şu anda çok hızlı bir silahlanma yarışı içinde olduğunu ve birkaç ayda bir dramatik biçimde değiştiğini anlıyordum.
      Bu, geliştirici kaynaklarının sınırlı olmasının sonucu da olabilir. 10 yıllık bir teknolojide böyle temel bir özelliğin eksik olması şaşırtıcı olurdu; ama silahlanma yarışı içindeki yapay zeka teknolojisinde bazı kolaylaştırıcı özelliklerin henüz eksik olması anlaşılabilir görünüyor.
    • Bu yaklaşımı gramer tabanlı örneklemeye genişlettik ve yukarıda bağlantısı verilen makalede açıkladık. İlgili PR https://github.com/normal-computing/outlines/pull/178.
    • https://arxiv.org/abs/2306.10763 içindeki “Guiding Language Models of Code with Global Context using Monitors”, dil modellerinin halüsinasyonlu dereference olmadan kod üretmesini sağlayan bir yöntemi gösteriyor.
  • Bunun aşağıdaki projelerden nasıl farklı olduğunu pek anlayamadım.
    https://github.com/1rgs/jsonformer
    https://github.com/newhouseb/clownfish
    https://github.com/mkuchnik/relm
    https://github.com/ggerganov/llama.cpp/pull/1773
    https://github.com/Shopify/torch-grammar
    Genel olarak bu tür logit tabanlı yönlendirme sistemleri çok sayıda var ve fazla traction alamamalarının nedeni, en iyi performanslı modellerin bu kadar ince ayarlı yaklaşımlara izin vermeyen REST API’lerin arkasında olması.
    O modeller çok daha iyi performans gösterdiği için insanlar genelde doğru biçim çıkana kadar yeniden istek göndermekle yetiniyor. GPT-4’te benim deneyimime göre bu tür başarısızlıklar da oldukça nadir.

    • clownfish ve relm’den haber verdiğin için teşekkürler. Bildiğim kadarıyla diğer kütüphaneler üretimin her adımında tüm sözlüğü dolaşıyor.
      Biz başlangıçta sözlüğü bir kez dolaşıp bir indeks oluşturuyoruz; sonraki üretim standart üretim kadar hızlı.
  • Başka şekilde açıklarsak, LLM her bir token ürettiğinde bir sonraki token'ın yalnızca geçerli bir JSON token'ı olmasını sağlayacak şekilde logit bias “maskesini” güncelliyor mu? Çok hoş

    • Tüm dizge geçerli olana kadar üretmeye devam etmesi gerekir; ama bir döngüye girerse ne olur bilmiyorum
      Bu yöntemin gerçekten %100 garanti verebildiğinden emin değilim
    • Doğru. Ayrıca maskeyi tüm sözlüğü dolaşmadan, sözlük aramasıyla güncelleyebilirsiniz. Tam dolaşım yavaş
    • JSON token'ları logit'lerle bire bir örtüşmediği için bir tür beam search ya da rejection sampling de gerekiyor
      Düzeltme: Makale bu kısmı daha dikkatli açıklıyor
    • Aslında çok eski bir teknik ve birçok kütüphane bunu yapıyor. Bu kütüphanede neyin bu kadar harika olduğunu pek anlayamadım
  • Bu Brandon Willard, Detroit'li break dansçı Brandon Willard mı?
    Düzeltme: Evet! https://brandonwillard.github.io/

    • Evet. Epey uzak geçmişte kaldı ama gerçekten eğlenceliydi
  • remilouf, kendi geçmişini “olasılıksal, ilişkisel, sembolik programlama” olarak anlattığına göre, düzenli gramerler ya da bağlamdan bağımsız gramerler, hatta fiilen herhangi bir düzeydeki gramerle metin üretmenin sorun olmadığını anlıyor olmalı
    Örneğin ilişkisel bir dil olan Prolog'da, yalnızca gramer verildiğinde Definite Clause Grammars gösterimiyle bunu yapmak çok kolay
    Bana göre bu yaklaşım kullanıcının grameri sağlamasını gerektiriyor. Öyleyse metin üretimi için LLM kullanmanın avantajı nedir, merak ediyorum
    İstenen metni üretmek için grameri doğrudan bir üreteç olarak çalıştırmamak için ne sebep var? Böylece LLM'i eğitmenin baştaki büyük zahmeti ve maliyeti azaltılabilir. Amaç yalnızca yapılandırılmış metin üretmekse, doğal dil modeli olan LLM'e neden gerek olduğu da soru işareti

    • O zaman tamamen rastgele ama geçerli bir çıktı elde edilmez mi? Burada istekle ilgili geçerli bir çıktı gerekiyor
      Yalnızca yapılandırılmış metin isteseniz bile LLM'e ihtiyaç duyulmasının nedeni, insanların yazdığı yapılandırılmamış metni ayrıştırıp makinenin kullanabileceği yapılandırılmış veriyi döndürmek
    • Hedef, gramere uyan herhangi bir rastgele dizge üretmek değil
      İstek “pi sayısının ilk 10 basamağı nedir?” ise ve yanıtı "[0-9]+\.[0-9]+" düzenli ifadesiyle sınırlandırdıysanız, amaç yalnızca kalıba uyan “1.2346789” gibi rastgele bir dizge değil, gerçek doğru yanıt olan 3.1415926535 değerini almaktır
    • IanCal her şeyi söylemiş. Yine de miniKanren ile LLM kullanmaya yönelik alternatif bir yaklaşım https://arxiv.org/abs/1809.02840 adresinde görülebilir
  • İlginç; yakın zamanda biz de llama çıktısını bir TypeScript interface ile uyumlu olacak şekilde kısıtlayan benzer bir araç yaptık[1]
    Çıktı biçimi garantisinin, LLM'lerin gerçek ve oyuncak olmayan kullanım alanlarında yer alacağı önümüzdeki on yıllar boyunca önemli olacağına kesinlikle inanıyorum
    [1] https://github.com/ggerganov/llama.cpp/discussions/2494