7 poin oleh GN⁺ 2024-09-03 | 1 komentar | Bagikan ke WhatsApp
  • Dengan structured outputs dari OpenAI API, dilakukan eksperimen pembuat web scraper berbantuan AI yang mengekstrak tabel HTML menjadi data terstruktur, dan GPT-4o menunjukkan kualitas ekstraksi yang lebih baik dari perkiraan pada beberapa tabel yang kompleks
  • Pada tabel dengan struktur tampilan yang kompleks seperti prakiraan 10 hari Weather.com, model dapat membedakan prakiraan siang/malam dan bahkan menemukan nilai yang tidak terlihat di layar dari sumber HTML
  • Pada tabel seperti Human Development Index di Wikipedia yang memiliki baris tergabung dengan nilai berulang, jumlah nilai per kolom menjadi tidak selaras sehingga rekonstruksi tabel sulit dilakukan, dan masalah ini tidak terselesaikan hanya dengan mengubah prompt
  • Untuk mengurangi biaya pemanggilan API, sempat dicoba juga pembuatan XPath, tetapi XPath yang dihasilkan ada yang salah atau mengembalikan hasil kosong; pendekatan yang lebih stabil adalah mengekstrak data terlebih dahulu lalu meminta XPath berdasarkan nilai tersebut
  • Dalam dua hari eksperimen, telah dihabiskan $24; setelah atribut HTML dikurangi, jumlah karakter turun setengah tanpa penurunan performa yang terlihat, tetapi validasi lanjutan tetap terbatas karena biaya

Mengekstrak tabel HTML dengan structured outputs

  • Fitur structured outputs dari OpenAI API digunakan untuk membangun web scraper berbantuan AI
  • Eksperimen pertama menggunakan pendekatan mengirim string HTML ke GPT-4o dan memintanya mengekstrak data tabel dalam bentuk terstruktur
  • Model Pydantic yang digunakan berupa ParsedTable, yang berisi nama tabel dan daftar kolom, serta struktur ParsedColumn, yang berisi nama kolom dan daftar nilainya
  • Dalam system prompt, model diberi peran sebagai web scraper ahli yang mengekstrak data terstruktur dari tabel HTML
  • GPT-4o mini juga sempat dicoba, tetapi hasilnya jauh lebih buruk sehingga eksperimen berikutnya dilakukan dengan GPT-4o

Kelebihan yang terlihat pada tabel kompleks

  • Setelah tabel sederhana, dimasukkan tabel prakiraan cuaca 10 hari dari Weather.com
  • Tabel ini memiliki satu baris besar di bagian atas, sementara 9 hari sisanya terdiri dari baris-baris yang lebih kecil
  • GPT-4o mengenali struktur prakiraan siang/malam pada 9 hari sisanya dan menambahkan kolom Day/Night
  • Awalnya kolom Condition yang diekstrak tampak seperti halusinasi, tetapi setelah memeriksa sumber HTML ternyata nilainya memang ada dalam tag yang tidak terlihat di layar

Kegagalan pada baris tergabung

  • Tabel Human Development Index di Wikipedia tampak sederhana, tetapi karena ada baris tergabung untuk nilai berulang, GPT-4o tidak dapat menanganinya dengan baik
  • Model memang mengekstrak tiap kolom sesuai instruksi, tetapi jumlah nilai pada tiap kolom berbeda sehingga hasilnya sulit direpresentasikan sebagai tabel
  • System prompt sempat diubah menjadi instruksi seperti “untuk baris tergabung, ekstrak menjadi beberapa nilai JSON agar semua kolom memiliki jumlah baris yang sama”, tetapi tetap tidak berhasil
  • Prompt yang mengarahkan ekstraksi berbasis baris alih-alih kolom masih belum dicoba

Keterbatasan pendekatan pembuatan XPath

  • Karena memanggil OpenAI API setiap saat bisa membuat biaya membengkak, dicoba pendekatan mengembalikan XPath alih-alih data hasil ekstraksi
  • Tujuannya adalah agar saat mengambil ulang data yang diperbarui dari halaman yang sama, scraping bisa dilakukan dengan XPath tanpa perlu memanggil model lagi
  • Prompt disusun agar menerima isi HTML dan nama kolom, lalu mengembalikan string XPath yang bisa dievaluasi di driver.find_elements(By.XPATH, xpath) milik Selenium
  • Pendekatan ini tidak stabil
    • Ada kasus ketika GPT-4o mengembalikan XPath yang salah
    • Menyebut Selenium dalam prompt sedikit membantu, tetapi tetap ada XPath yang mengembalikan data salah atau hasil kosong

Menggabungkan ekstraksi data dan pembuatan XPath

  • Percobaan berikutnya adalah meminta GPT-4o mengekstrak data terlebih dahulu, lalu menggunakan hasil tersebut sebagai nilai referensi saat meminta XPath
  • Kombinasi ini bekerja jauh lebih baik dibanding langsung meminta XPath sejak awal
  • Karena ada kasus XPath yang dihasilkan tidak mengembalikan hasil, ditambahkan logika retry sederhana untuk mencoba lagi jika hasil kosong
  • Pada tabel yang diuji, pendekatan retry ini efektif
  • Namun masalah baru juga muncul
    • Pada tahap pertama, ekstraksi data kadang mengubah gambar menjadi teks
    • Misalnya, gambar panah ke atas bisa diekstrak sebagai teks seperti arrow-upwards
    • Tahap kedua lalu mencoba mencari teks yang sebenarnya tidak ada di HTML, sehingga gagal
    • Masalah ini belum diperbaiki secara khusus

Biaya dan pembersihan HTML

  • Saat menggunakan GPT-4o untuk web scraping, bahkan tabel HTML kecil pun bisa memuat banyak karakter sehingga biaya menjadi tinggi
  • Dalam dua hari eksperimen, sudah dihabiskan $24
  • Untuk menurunkan biaya, ditambahkan logika pembersihan yang membuang data tidak perlu dari string HTML sebelum dikirim ke model
  • Setelah semua atribut dihapus kecuali class, id, dan data-testid yang paling sering dipakai oleh XPath yang dihasilkan, jumlah karakter tabel berkurang setengah
  • Setelah pembersihan ini, tidak terlihat penurunan performa, dan bahkan kualitas ekstraksi bisa saja membaik
  • Saat ini, tahap pembuatan XPath masih melakukan satu pemanggilan model untuk setiap kolom tabel
  • Perbaikan untuk menghasilkan beberapa XPath sekaligus dalam satu kali jalan mungkin dilakukan, tetapi belum dicoba atau dievaluasi performanya

Demo dan ide eksperimen lanjutan

  • Kualitas ekstraksi GPT-4o memang mengesankan, tetapi biaya yang harus dibayarkan ke OpenAI juga terasa besar
  • Demo sederhana yang dibuat dengan Streamlit dapat dilihat di https://orange-resonance-9766.ploomberapp.io
  • Kode sumber dipublikasikan di GitHub, disertai catatan agar tidak mengharapkan alat yang benar-benar matang
  • Ingin menguji lebih banyak tabel, tetapi karena biaya OpenAI meningkat, eksperimen hanya dilakukan pada sedikit tabel
  • Jika ada lebih banyak waktu, rencananya akan mencoba hal-hal berikut
    • Demo saat ini adalah proses sekali jalan di mana pengguna memasukkan URL dan XPath awal; pengalaman pengguna bisa jadi lebih baik jika pengguna dapat mengklik tabel yang ingin diekstrak dan memberikan contoh baris
    • Pada tabel kompleks, mengekstrak seluruh kolom dengan satu XPath saja mungkin sulit, sehingga ingin diuji pendekatan meminta LLM mengembalikan program seperti Python
    • Karena biaya penggunaan GPT-4o terasa mahal dan banyak data tidak perlu ikut dikirim, metode pembersihan HTML masih perlu dieksplorasi lebih lanjut

1 komentar

 
GN⁺ 2024-09-03
Pendapat di Hacker News
  • Hasilnya paling baik ketika HTML terlebih dahulu diubah ke format sederhana seperti Markdown, alih-alih langsung memasukkan HTML ke LLM
    Alat yang pernah saya gunakan antara lain Extractus https://github.com/extractus dan dom-to-semantic-markdown https://github.com/romansky/dom-to-semantic-markdown
    Magic Loops https://magicloops.dev/ yang berjalan di cloud menggunakan Apify https://apify.com/ dan Firecrawl https://www.firecrawl.dev/ di dalamnya, sementara Chrome Extension menggunakan dom-to-semantic-markdown
    Saat ini kami sedang bereksperimen dengan cara membuat XPath khusus situs melalui alur berbantuan pengguna, lalu sebelum memanggil LLM hanya mengekstrak elemen yang diperlukan; setelah masalahnya disederhanakan, GPT-4o mini pun hasilnya cukup bagus

    • Akan senang jika kalian juga melihat https://browserbase.com/ yang kami buat
      Karena Chrome Extension bisa dijalankan di browser headless, konversi semantik ke Markdown dapat dilakukan di dalam browser sebelum data dikeluarkan
      Ada juga tampilan real-time browser yang bisa di-iFrame, sehingga pengguna bisa langsung memberi masukan terhadap XPath yang sedang dibuat: https://docs.browserbase.com/features/session-live-view#give...
    • Saya penasaran apakah sudah dibandingkan antara mengubah ke Markdown dan pendekatan yang hanya melakukan hal seperti menghapus atribut tag dari HTML, membuka tautan, serta menghapus elemen yang tidak ditampilkan
      Dalam pengalaman saya, performanya cukup mirip dengan Markdown, sementara transformasinya lebih mudah dan kasus pengecualiannya lebih sedikit
    • Saya baru pertama kali mendengar Semantic Markdown https://hackmd.io/@sparna/semantic-markdown-draft, tetapi sepertinya ini cara memasukkan data RDF ke dalam dokumen Markdown
      Karena halaman yang saya temukan bertuliskan “Alpha Draft”, tampaknya belum banyak korpus konten Semantic Markdown, dan kurangnya data pelatihan bisa saja mengganggu pemahaman LLM
      Meski begitu, formatnya cukup mudah dibaca, jadi jika LLM memperlakukan metadata terstruktur seperti penjelasan dalam tanda kurung, sepertinya bisa ditangani dengan cukup baik
    • Saya pernah melakukan hal serupa dalam konteks berbeda: JSON kompleks yang merepresentasikan grafik eksekusi terlebih dahulu diubah ke format Graphviz dot yang lebih sederhana, lalu dimasukkan ke LLM, dan hasilnya cukup bagus
  • OpenAI baru-baru ini mengumumkan Batch API, sehingga semua prompt bisa disiapkan lalu dijalankan secara batch, dan biayanya juga turun menjadi 50%: https://platform.openai.com/docs/guides/batch
    Dulu saya sering menggunakannya dengan GPT-4o mini, dan bisa memproses 3.000 item dalam waktu kurang dari 5 menit
    Ini bisa cukup bagus untuk aplikasi yang tidak membutuhkan real-time

    • Saya berharap server inferensi open-source juga segera mendukung endpoint itu
      vLLM sudah menambahkan sebagian dukungan “offline batch mode” dengan format yang sama, tetapi belum sampai pada implementasi endpoint OpenAI
    • Penawaran OpenAI bagus, tetapi dibandingkan metode ekstraksi teks tradisional yang menghasilkan presisi dan recall serupa, menurut saya masih lebih mahal sekitar satu atau dua digit
    • Ini keputusan yang benar-benar bagus dari OpenAI, dan saya berharap alat cloud lain seperti Azure juga menyediakan fitur yang sama
      Ini fitur yang terasa sangat alami
  • Untuk konten terstruktur, misalnya daftar item atau tabel sederhana, sebenarnya LLM tidak diperlukan
    Baru-baru ini saya membuat web scraper https://easyscraper.com yang bekerja otomatis di situs web apa pun, dan versi awalnya dibuat dengan AI, tetapi pada akhirnya heuristik berbasis atribut elemen dan posisi lebih cepat, murah, dan akurat
    Di sebagian besar situs web, pendekatan non-AI bekerja sangat baik, jadi sebaiknya periksa dulu apakah AI benar-benar diperlukan, misalnya ketika datanya tidak terstruktur atau ketika format keluaran harus diturunkan dari data halaman

    • LLM lebih tahan terhadap pembaruan situs web yang bisa merusak scraping biasa
      Seperti penulisnya, Anda bisa membuat LLM menghasilkan XPath, lalu biasanya melakukan scraping biasa dengan XPath tersebut, dan jika rusak, gunakan LLM untuk memperbarui XPath
      Meski begitu, jika data tidak mengalir lagi atau pipeline di bagian belakang rusak karena format yang tidak terduga, barulah beri tahu manusia
    • Ini pertama kalinya saya melihat alat yang memungkinkan kita memilih langsung apa yang ingin di-scrape
      Saya selalu penasaran mengapa alat seperti ini tidak ada
  • Penasaran apakah sudah ada sesuatu seperti “HTML reducer
    Kalau melihat source halaman apa adanya, 90% token adalah sampah karena JavaScript acak, iklan, atribut yang tidak perlu, dan nesting berlebihan untuk rendering
    Jika menelusuri dengan parser DOM lalu hanya menyisakan node yang berisi teks, struktur HTML, dan atribut tag yang diperlukan (sekitar class/id), sepertinya biaya bisa sangat dikurangi, dan pendekatan XPath juga bisa bekerja lebih baik
    Readability juga dipakai, tetapi struktur DOM hilang, dan kualitasnya menurun pada situs web yang banyak JavaScript atau halaman yang memperluas teks seperti “continue reading”
    Penasaran alat apa yang paling mendekati standar untuk kebutuhan seperti ini

  • Mengejutkan bahwa penulis sudah mengerjakan 99% pekerjaan dan penulisan, tetapi tidak mengunduh bagian 1% sisanya, yaitu engine berbasis ollama atau llama.cpp, untuk menguji LLM lokal yang layak
    Untuk use case ini, model 7B atau 30B juga bisa bekerja dengan baik, dan biaya menjalankannya cukup rendah sehingga GPT-4o mungkin tidak diperlukan

    • Saran yang bagus
      Saya baru mulai mengutak-atik LLM, dan berencana melihat model yang di-host secara lokal juga
  • Di Kadoa https://kadoa.com kami telah melakukan web scraping otomatis berbasis AI, dan eksperimen awalnya mirip dengan tulisan ini
    Kami mulai sejak masa ketika hanya ada GPT-3 yang mahal dan lambat, sehingga membutuhkan solusi yang hemat biaya dalam skala besar
    Pada akhirnya, alih-alih memakai LLM setiap kali pada tahap ekstraksi, kami membuat kode ekstraksi selector CSS atau XPath lewat code generation, lalu menyesuaikan kode scraper mengikuti perubahan situs web
    Untuk pembersihan dan transformasi kami memakai LLM kecil yang di-fine-tune, dan untuk validasi kami menilai kualitas data dengan LLM-as-a-judge bersama metode tradisional seperti pencarian balik
    Menerapkannya pada beberapa sumber data sederhana dan menjalankannya secara stabil, skalabel, serta hemat biaya di ribuan situs web adalah masalah yang sama sekali berbeda, dan pendekatan yang tepat adalah mencampurkan rekayasa ETL tradisional dengan tahap-tahap LLM kecil yang dievaluasi dengan baik

  • Kalau memberikan contoh HTML yang ingin di-scrape lalu meminta cuplikan kode BeautifulSoup, hasilnya cukup bagus
    Biasanya struktur yang ingin diambil tetap dipertahankan, tetapi menulis sendiri string parsing yang rumit itu membosankan
    Menyerahkan parsing sebenarnya ke LLM itu berlebihan, dan ada risiko hasilnya terkontaminasi halusinasi

  • Jika HTML dipraproses terlebih dahulu, hasilnya bisa lebih murah dan lebih baik
    Sepertinya belum disebut, tetapi secara pribadi saya mendapatkan hasil bagus dengan trafilatura https://trafilatura.readthedocs.io/en/latest/

    • Sangat setuju soal trafilatura
      Karena cukup mengirim teks saja ke LLM, biaya bisa ditekan sangat besar
      Saya juga memakainya di proyek terbaru https://github.com/philippe2803/contentmap, sebuah library Python sederhana yang membuat vector store untuk situs web arbitrer dengan menjadikan sitemap XML domain sebagai titik awal
      Karena struktur HTML berbeda di tiap domain, kami perlu mengambil hanya konten sebenarnya dan menghapus tag HTML dan sebagainya; Trafilatura melakukan itu untuk hampir semua URL hanya dengan beberapa baris kode
  • Ini pertama kalinya saya melihat artikel dengan begitu banyak tag oranye
    Di NewsCatcher, kami banyak melakukan pengujian dengan GPT-4o, dan setelah merayapi lebih dari 100 ribu situs web berita, kami harus mem-parse konten berita
    Model berbasis aturan untuk mengekstrak data dari artikel mana pun bekerja cukup baik, dan kami tidak menemukan cara untuk meningkatkannya lebih jauh dengan GPT
    Yang lebih menarik adalah sisi crawling: kita harus mengetahui semua lokasi tempat artikel berita bisa dipublikasikan, dan terkadang ada lebih dari 50 subbagian
    Karena struktur tiap situs web tidak sering berubah, menurut saya untuk banyak proyek, pendekatan menghasilkan kode ekstraksi sudah bisa memadai
    Jadi kami sedang melihat kemungkinan menggunakan LLM untuk menghasilkan kode parsing HTML; jika tertarik, hubungi artem [at] newscatcherapi.com

    • Saya ingin mencoba ini untuk proyek hobi
      Akan bagus kalau ada pendaftaran mandiri
  • Web scraping adalah alasan nyata saya dan co-founder membuat openpipe.ai yang sekarang
    GPT-4 benar-benar sangat bagus untuk pekerjaan ini, tetapi terlalu mahal
    Namun, kemampuan untuk melakukan scraping pada jenis situs tertentu cukup mudah didistilasi ke model fine-tuning yang jauh lebih murah, dan pada jenis situs itu hasil scraping-nya stabil dan bagus

    • Kyle, seharusnya saya mengatakan ini lebih awal
      Kami juga sudah cukup lama mengerjakan masalah ini, dan saya akan menghubungi untuk menunjukkan sejauh mana progres kami