法律は私たちの社会のソースコードですが、それはしばしばそれを支配する人々にとってアクセス不可能な方法で書かれています。法案は数十ページ長く、密集した法的言語や交差点で満たされ、それらを偶然に読むことはほとんど不可能です。開発者として、私は政府をより透明かつアクセス可能にするために技術を使用することを信じています。 もし私がデータを使用してAIを訓練して請求書を読み、自身の概要を書くことができればどうでしょうか? これが、データの掃除から混乱の片付けまで、強力な言語モデルの細かい調節まで、これを実行するためのエンド-to-エンドパイプラインを構築する方法の物語です。 The Basic Toolkit: BeautifulSoup For simple HTML pages and Python's urllib are the perfect tools. I started by writing a script (all_house_texas.py) to navigate the Bills Filed pages, find all the links to individual bill histories, and extract basic information such as the author and caption. 基本的なツールは、簡単なHTMLページとPython's urllibです。 第1部:20世紀政府のウェブサイトの削除 # From: leg_module_test.py # A simple function to turn a URL into a BeautifulSoup object import urllib.request from bs4 import BeautifulSoup def make_soup(url): thepage = urllib.request.urlopen(url) soupdata = BeautifulSoup(thepage, "lxml") return soupdata website ='https://capitol.texas.gov/BillLookup/History.aspx?LegSess=89R&Bill=SB1' soup = make_soup(website) # Find the author's name by its specific HTML ID for data in soup.findAll('td', id = 'cellAuthors'): print(data.text) これは初期データではうまく機能しましたが、すぐに壁にぶつかりました。 「Selenium for JavaScript」 最も価値のあるデータは、標準的なリンクではありませんでした. それは新しいポップアップウィンドウを開くJavaScriptオンクリックイベントの背後に隠れていました. BeautifulSoupはJavaScriptを実行できないので、リンクを見ることができませんでした. これは現代のウェブスクラップにおける共通の課題です。 Seleniumを使用して、私のスクリプトはページをロードし、JavaScriptがレンダリングするのを待って、人間のようにボタンと相互作用することができます。 Selenium 私のスクリプト texas_leg_txt_from_list.py は、このアプローチを使用して、ようやく概要URLを取得しました。 # From: texas_leg_txt_from_list.py # Using Selenium to find an element and extract its JavaScript-based URL from selenium import webdriver from selenium.webdriver.common.by import By import time # ... (driver setup code) ... driver.get('https://capitol.texas.gov/BillLookup/Text.aspx?LegSess=75R&Bill=HB1') time.sleep(1.5) # Wait for the page to load # Find the summary link by its ID bill_summary_link = driver.find_element(By.ID, 'lnkBillSumm') # Get the 'onclick' attribute, which contains the JavaScript function call onclick_attribute = bill_summary_link.get_attribute('onclick') # A bit of string manipulation to extract the URL from the JavaScript start_index = onclick_attribute.find("('") + 2 end_index = onclick_attribute.find("'", start_index) bill_summary_url = 'https://capitol.texas.gov/BillLookup/' + onclick_attribute[start_index:end_index] print(f"Successfully extracted summary URL: {bill_summary_url}") driver.quit() これにより、私は何千もの請求書のための私の3つの重要なデータを信頼できるように収集することができます:メインページのURL、完全な登録されたテキスト、および公式の概要テキスト。 Part 2: The Cleanup Crew - クリーンデータにHTMLの混乱を変える Web データは混乱しています. クロックされたテキストは、追加のホワイトスペース、非破壊スペース文字(\xa0)、およびその他の HTML アーティファクトで満たされていました. モデルにこれを供給する前に、それは深刻なクリーニングが必要でした. 私の start_analysis_0.py スクリプトは、この重要なステップに専念しました。 まず、regex を使用してシンプルなクリーニング機能を書き、ホワイトスペースを標準化し、スムック文字を削除しました。 # From: start_analysis_0.py # A function to clean raw text scraped from the web import re def clean_text(text): if not isinstance(text, str): return "" # Handle cases where data might not be a string text = re.sub(r'\s+', ' ', text) # Collapse all whitespace into single spaces text = text.replace('\xa0', ' ') # Remove non-breaking spaces text = text.replace('__','') # ... other replacements ... return text.strip() 次に、私は重要な品質管理チェックを実施しました。良い概要は、元のテキストよりもはるかに短く、しかしそれは役に立たないほど短くではありませんでした。私は、概要の長さが全体の請求書の長さの10%から100%の間にあったカップルだけを保持することを決定しました。 このビジュアル化により、私のデータのほとんどが健康な配布に落ちており、フィルタリングの論理を検証しました。 Part 3: Fine-Tuning a T5 モデル さて、面白い部分は、使ってみることにしました。 強力で多様なテキストトランスファーザー T5は、タスクに従っての指示のための素晴らしいです。概要でテキストを予備することにより、私は 私のトレーニングパイプラインは、Hugging Face トランスフォーマーと TensorFlow ライブラリを使用して start_analysis_1.py と start_analysis_2.py で構築されました。 T5小型モデル モデルを教える コアプロセスはこんな感じです。 Tokenization: このステップでは、テキストをモデルが理解できる数値IDに変換します. I created a pre-processing function to handle this for both the bill text (the input) and the summary (the target label). # From: start_analysis_1.py # This function tokenizes the text and prepares it for the model from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained('t5-small') prefix = "summarize: " def preprocess_function(examples): # Prepare the input text with the "summarize: " prefix inputs = [prefix + doc for doc in examples["source_text"]] model_inputs = tokenizer(inputs, max_length=512, truncation=True) # Tokenize the target summaries with tokenizer.as_target_tokenizer(): labels = tokenizer(examples["target_text"], max_length=128, truncation=True) model_inputs["labels"] = labels["input_ids"] return model_inputs データロード:私はクリーン JSON を Hugging Face Dataset オブジェクトにロードし、トークニケーションを適用しました。 トレーニング: 最後に、私はモデルを構成し、最適化を設定し、モデル.fit()でトレーニングプロセスを開始しました。そこで魔法が起こります。 # From: start_analysis_1.py # The final training call in TensorFlow import tensorflow as tf from transformers import TFAutoModelForSeq2SeqLM, AdamWeightDecay # ... (dataset and data_collator setup) ... optimizer = AdamWeightDecay(learning_rate=2e-5, weight_decay_rate=0.01) model = TFAutoModelForSeq2SeqLM.from_pretrained("t5-small") model.compile(optimizer=optimizer) # Let's train! model.fit( x=tf_train_set, validation_data=tf_test_set, epochs=3 ) # Save the fine-tuned model for later use model.save_pretrained("./t5_small_texas_bills") Part 4: The Verdict - Does It Work? 数時間のトレーニングの後、真実の瞬間がやってきた. 私はモデルにこれまで見たことのない口座を食べて、それが何を生み出すかを見ました. こちらは一例: **Original Bill Text (Snippet): \ "...A ACT relating to providing for a reduction on a limitation on the total amount of ad valorem taxes that may be imposed by a school district on the residence homesteads of the elderly or disabled to reflect any reduction in the school district's tax rate and protecting a school district against any resulting loss in local income..." **Original Bill Text (Snippet): \ "...A ACT relating to providing for a reduction on a limitation on the total amount of ad valorem taxes that may be imposed by a school district on the residence homesteads of the elderly or disabled to reflect any reduction in the school district's tax rate and protecting a school district against any resulting loss in local income..." **公式概要(地元の真実): \ 「この法律は、高齢者または障害のある住宅所有者の学校区税の限界を減らし、税率削減を反映します。 **公式概要(地元の真実): \ 「この法律は、高齢者または障害のある住宅所有者の学校区税の限界を減らし、税率削減を反映します。 「この法案は、高齢者または障害者の居住ホームステイに学校区が課す可能性のある価値税の総額の制限を減らすことに関連しています。 「この法案は、高齢者または障害者の居住ホームステイに学校区が課す可能性のある価値税の総額の制限を減らすことに関連しています。 分析: モデルは、主な主体(価値税、学校区、高齢者/障害者ホームステッド)とコアアクション(税制限を減らす)を正しく識別しました。人間の概要ほど説得力のあるものではありませんが、正確であり、法案の本質を完璧に捉えています。 分析: モデルは、主な主体(価値税、学校区、高齢者/障害者ホームステッド)とコアアクション(税制限を減らす)を正しく識別しました。人間の概要ほど説得力のあるものではありませんが、正確であり、法案の本質を完璧に捉えています。 結論 このプロジェクトは、最も影響力のあるAIアプリケーションがしばしばグリッティなデータエンジニアリングの基盤に依存していることを強力な思い出させてくれました。 最終モデルは完璧ではないが、強力なコンセプトの証明であり、現代のAIを用いて複雑な市民情報を誰にでもアクセスできることを示している。 What's next? API として展開:誰でも請求書のテキストを提出し、概要を得ることができる公共サービスに変換します。 ボットを作成する:新しく提出された請求書の概要を投稿する。 他の州への拡大:すべての立法機関は同じ問題を抱え、このパイプライン全体を調整することができる。 もしあなたが開発者なら、あなた自身の地方政府のデータを見ることをお勧めします. あなたはあなたのスキルを強化するだけでなく、あなたのコミュニティに役立つ何かを構築する類似の機会を見つけるかもしれません。