Законодателството е изходният код на нашето общество, но често е написано по начин, който е недостъпен за самите хора, които управлява.Проектите могат да бъдат десетки страници дълги, пълни с плътни правни и кръстосани препратки, които ги правят почти невъзможни за четене случайно.Като разработчик вярвам в използването на технологии, за да направя правителството по-прозрачно и достъпно. Какво ще стане, ако мога да използвам данните, за да обуча AI да чете всяка сметка и да напише собствено резюме?Това е историята за това как изградих тръбопровод от край до край, за да направя точно това: от изваждането на данните, до почистването на бъркотията, до фина настройка на мощен езиков модел. Първата стъпка беше да се получат URL адресите за всеки законопроект, който е преминал, заедно с пълния му текст и официалното му обобщение. The Basic Toolkit: BeautifulSoup За прости HTML страници и urllib на Python са перфектните инструменти. започнах с писане на скрипт (all_house_texas.py) за навигация в страниците с законопроекти, намиране на всички връзки към отделните истории за фактури и извличане на основна информация като автора и подписи. Част 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 за 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() С това мога надеждно да събера трите ми ключови части от данни за хиляди фактури: URL адреса на главната страница, пълния записван текст и официалния резюме текст. Част 2: Екипът за почистване - превръщане на хаоса в HTML в чисти данни Уеб данните са объркани. отрязаният текст е пълен с допълнително бяло пространство, неразбиващи се пространствени знаци (\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% от дължината на цялата сметка. Тази визуализация потвърди, че повечето от моите данни попадат в здравословно разпределение, валидирайки логиката ми за филтриране. Част 3: Фино настройване на модел T5 Сега за забавната част.Избрах да използвам Мощен и гъвкав трансформатор за прехвърляне на текст към текст. T5 е чудесен за инструкции след задачи. Моят тренировъчен тръбопровод е изграден в start_analysis_1.py и start_analysis_2.py с помощта на трансформаторите Hugging Face и библиотеките TensorFlow. T5 малък модел Научете модела Основният процес изглежда така: Токенизация: Тази стъпка преобразува текста в цифрови идентификатори, които моделът може да разбере. създадох функция за предварителна обработка, за да се справя с това както за текста на фактурата (входа), така и за резюмето (целевия етикет). # 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 и приложих токенизацията. Обучение: Накрая конфигурирах модела, създадох оптимизатор и стартирах процеса на обучение с model.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") Част 4: Съдът - дали е работил? След часове на обучение, моментът на истината дойде. дадох на модела сметка, която никога не е виждал преди, за да видя какво ще произведе. Ето един пример: **Оригинален текст на законопроекта (Snippet): "...Акт, свързан с предвиждането на намаляване на ограничението върху общия размер на данъците ad valorem, които могат да бъдат наложени от училищния окръг върху жилищните домове на възрастните хора или хората с увреждания, за да се отрази всяко намаляване на данъчната ставка на училищния окръг и да се защити училищният окръг от всяка възникнала загуба на местни приходи..." **Оригинален текст на законопроекта (Snippet): "...Акт, свързан с предвиждането на намаляване на ограничението върху общия размер на данъците ad valorem, които могат да бъдат наложени от училищния окръг върху жилищните домове на възрастните хора или хората с увреждания, за да се отрази всяко намаляване на данъчната ставка на училищния окръг и да се защити училищният окръг от всяка възникнала загуба на местни приходи..." **Официално резюме (Официална истина): \ "Настоящият закон намалява ограничението на данъците ad valorem за училищни райони за възрастни или инвалидни собственици на жилища, за да отразява намалените данъчни ставки. Той гарантира, че училищните райони се компенсират за всяка загуба на приходи. **Официално резюме (Официална истина): \ "Настоящият закон намалява ограничението на данъците ad valorem за училищни райони за възрастни или инвалидни собственици на жилища, за да отразява намалените данъчни ставки. Той гарантира, че училищните райони се компенсират за всяка загуба на приходи. ** AI-Generated Резюме: "Законопроектът се отнася до намаляване на ограничението върху общия размер на данъците ad valorem, които могат да бъдат наложени от училищен район върху жилищните домове на възрастните хора или хората с увреждания. ** AI-Generated Резюме: "Законопроектът се отнася до намаляване на ограничението върху общия размер на данъците ad valorem, които могат да бъдат наложени от училищен район върху жилищните домове на възрастните хора или хората с увреждания. Анализ: Моделът правилно идентифицира основните субекти (данъци ad valorem, училищни райони, възрастни / домакинства с увреждания) и основното действие (намаляване на данъчното ограничение). Докато не е толкова изразително, колкото човешкото обобщение, то е точно и улавя същността на сметката перфектно. Моделът правилно идентифицира основните субекти (данъци ad valorem, училищни райони, възрастни / домакинства с увреждания) и основното действие (намаляване на данъчното ограничение). Докато не е толкова изразен, колкото човешкото резюме, той е точен и улавя същността на сметката перфектно. Analysis: Заключението Този проект беше мощно напомняне, че най-влиятелните приложения на ИИ често разчитат на основите на грубото инженерство на данните.Създаването на модела беше последните 20% от работата; първите 80% бяха трудоемкият процес на придобиване и почистване на данните. Последният модел не е перфектен, но е мощно доказателство за концепцията.Той демонстрира, че можем да използваме съвременния ИИ, за да направим сложната гражданска информация по-достъпна за всички. What's next? Разполагане като API: Превърнете това в публична услуга, където всеки може да подаде текста на фактурата и да получи обобщение. Създаване на бот: За публикуване на резюмета на новопостъпилите фактури. Разширяване до други държави: Всеки законодателен орган има един и същ проблем. Ако сте разработчик, ви насърчавам да погледнете данните на собственото си местно правителство.Може да намерите подобна възможност да изградите нещо, което не само подобрява уменията ви, но и служи на вашата общност.