Als u werkt in een bedrijf dat webgegevens gebruikt, weet u zeker dat het slechts de eerste laag van een complexer product is. In feite zijn web-scraped data traditioneel opgeslagen in bestanden of databases (cloud storage buckets, data lakes, of data warehouses) en vervolgens geanalyseerd met behulp van Business Intelligence (BI) -tools, zowel commerciële als proprietaire. Bijvoorbeeld, een team kan productprijzen of klantrecensies van het web scrapen, de ruwe gegevens opslaan als CSV / JSON-bestanden, deze in een SQL-gegevensopslagplaats laden en vervolgens BI-platforms zoals Tableau of Power BI gebruiken om dashboards en rapporten te maken. Moderne webscraping-oplossingen produceren zelfs gegevens in gestructureerde formaten (CSV, J Tegenwoordig veranderen grote taalmodellen (LLM's) dit paradigma. In plaats van alleen te vertrouwen op statische dashboards of SQL-verzoeken, kunnen organisaties AI-assistenten gebruiken om inzichten te verkrijgen uit geschrapeerde gegevens via natuurlijke taalopdrachten. Met andere woorden, in plaats van een mens een query te schrijven of een grafiek te interpreteren, kan een AI-assistent direct vragen beantwoorden over de gegevens. Denk na over het hebben van uw ChatGPT-achtige interface en schrijf een paar opdrachten om inzichten te krijgen, de creatie van dashboards te omzeilen. Ik heb dit soort benaderingen gezien in verschillende producten voordat LLM's uitkwamen, maar zonder groot succes. Het evoluerende AI-landschap en de wekelijkse verbeteringen die we in LLM's Stel je voor te vragen, Deze aanpak belooft snellere, intuïtiever toegang tot informatie voor niet-technische gebruikers zonder de overhead van het bouwen van grafieken of het schrijven van code. "Welke concurrent had de hoogste prijs in het afgelopen kwartaal?" Natuurlijk ontstaat er een nieuwe reeks uitdagingen: hoe zit het met hallucinaties?Als we het onderliggende aantal van een antwoord niet zien, kunnen we 100% zeker zijn dat het antwoord correct is? In dit bericht (en de volgende in de Lab-serie) zullen we een end-to-end project bouwen waar we beginnen met het scrapen van de artikelen in deze nieuwsbrief, ze in een database plaatsen die geschikt is voor AI-gebruik, deze kennis ophalen en vervolgens een webapp publiceren die een verrijkte versie van een GPT-model kan gebruiken. Het verbeteren van LLM kennis Het integreren van aangepaste gegevens (zoals uw gesneden dataset) in een LLM kan voornamelijk op twee manieren worden gedaan: door Het model of het gebruik van , en elk van deze methoden heeft voor- en nadelen.Laten we eens kijken hoe ze verschillen en welke aanpak het beste zou kunnen zijn voor ons gebruik. fine-tuning Retrieval-Augmented Generation (RAG) Fine-Tuning versus Retrieval-Augmented Generation betekent het trainen van de basis LLM op aanvullende gegevens zodat het nieuwe kennis absorbeert. In essentie, neem je een vooraf getraind model en ga verder met het trainen op uw domein-specifieke dataset, het aanpassen van de gewichten om die kennis in te vullen. Bijvoorbeeld, als je een verzameling technische artikelen hebt geschrapt, zou je een LLM op die artikelen kunnen afstemmen. Fine-tuning wordt vaak gedaan door het model te voorzien van een grote set van vraag-en-antwoord-paren of tekstpassages uit uw gegevens, zodat het leert te reageren met die informatie wanneer relevant. De volgende keer dat u het model opvraagt, kan het gebruik maken van deze gebakken informatie zonder hulp van buitenaf. Fine-tuning intrinsically knows augmented from the inside neemt een andere aanpak: het model blijft ongewijzigd, maar we geven het toegang tot een externe kennisbasis (meestal via een vectorzoek). De LLM genereert vervolgens zijn antwoord met behulp van die aanvullende context. Voor boomers zoals ik, overweeg het als het invoegen van een CD in het hoofd van de Neo in de Matrix om nieuwe vaardigheden en bewegingen te leren. In ons geval zou de kennisbasis een verzameling van geschrapeerde webartikelen kunnen zijn die zijn opgeslagen in een gespecialiseerde database. RAG is als een open-book examen voor de LLM - op query-tijd kijkt het naar de relevante "pagina" van gegevens en gebruikt het om een antwoord te formuleren, in plaats van alleen op zijn interne geheugen te vertrouwen. Retrieval-Augmented Generation (RAG) retrieve relevant documents Zoals je je kunt voorstellen, is een belangrijk verschil waar de extra kennis blijft: met fijne aanpassing is de kennis ingebed. (de gewichten van het model worden bijgewerkt). met RAG blijft de kennis Fine-tuning is vergelijkbaar met het leren van het model nieuwe feiten permanent, terwijl RAG is als het uitrusten van het model met een dynamische bibliotheek die het kan verwijzen op de fly. in the model itself external De twee benaderingen hebben verschillende voor- en nadelen: Fine-Tuning: Once fine-tuned, the model can respond faster and more integratedly to new knowledge. It doesn't need lengthy prompts with documents each time. A well-fine-tuned model typically outperforms the base model on domain-specific questions because it has a deeper understanding of that niche terminology and content. Pros: Fine-tuning can be resource-intensive and time-consuming – you need sufficient training data and computing power (or budget if using a service). It also makes the model static concerning that training snapshot. If your scraped data changes or new information comes in, you’d have to fine-tune again to update the model. There’s also a risk of the model or overriding some of its original knowledge if not carefully managed. Importantly, fine-tuning means your data becomes part of the model’s parameters, which could be a privacy concern if the model weights are exposed or if using a third-party service to fine-tune (your data is uploaded for training). Last but not least, once the knowledge is embedded in the model, you cannot cite any article used to improve it. Cons: forgetting Retrieval-Augmented Generation (RAG): No need to modify the LLM itself – you leave the base model as-is and simply provide relevant context at query time. This makes updating or expanding the knowledge base easy: add or remove documents in your external index, and the model will use the latest data. It’s very flexible and (which can be more secure). RAG can reduce hallucinations by grounding answers in real sources – essentially, the model has the “receipts” to back up its answer. It also typically requires less upfront work than full fine-tuning; most effort goes into setting up the retrieval system. Pros: keeps your proprietary data external RAG introduces more moving parts – you need a system for embedding and indexing documents and retrieving them at runtime. At query time, you pay the cost in latency and token length for feeding documents into the model’s prompt. If the retrieved documents aren’t relevant (due to a bad query or vector mismatch), the answer will suffer. The LLM is also limited by its input size; if the documents plus question exceeds the model’s context window, you might have to truncate or select fewer documents. Additionally, the raw text of documents might influence the model's style, which could lead to less coherent or conversational answers unless you prompt it to refine the wording. Cons: Kortom, fijne aanpassing baken in een gefocust begrip, terwijl RAG real-time toegang tot kennis mogelijk maakt.Voor ons gebruik van het integreren van voortdurend bijgewerkte gesneden gegevens, lijkt RAG een betere aanpak: u kunt continu in nieuwe webgegevens trekken en uw assistent het onmiddellijk gebruiken in plaats van periodiek het hele model opnieuw te trainen. Voordat je verder gaat, is het de moeite waard op te merken dat fine-tuning en RAG niet wederzijds uitsluitend zijn; ze kunnen elkaar aanvullen.Bijvoorbeeld, je zou een model kunnen fine-tune om zijn toon of het vermogen om instructies te volgen aan te passen (of om kennis die klein en statisch is toe te voegen), en nog steeds gebruik RAG om het toegang te geven tot een grotere kennisbasis die vaak wordt bijgewerkt. Gebruik van een lokaal model vs. een externe API Een andere overweging is voor uw AI-assistent: een lokaal (open-source) model dat u zelf uitvoert of een gehost model via een API (zoals OpenAI's GPT-3.5/GPT-4 of anderen). what LLM to use Modellen zoals LLaMA 2, Mistral of Falcon kunnen op uw eigen servers worden uitgevoerd. Uw gerapporteerde gegevens verlaten nooit uw omgeving, wat belangrijk is als het gevoelige informatie bevat. U kunt ze vrij op uw gegevens afstemmen of wijzigen hoe ze werken. Kostenbewust kan het uitvoeren van een lokaal model goedkoper zijn voor grote hoeveelheden query's (geen API-kosten), maar u moet investeren in hardware of cloudinfrastructuur om het te hosten. Het nadeel is dat veel open modellen niet kunnen overeenkomen met de prestaties van de nieuwste GPT's. U moet mogelijk grotere of meer gespecialiseerde modellen gebruiken om vergelijkbare prestaties te krijgen, wat complex kan zijn om te beheren. Bovendien is het onderhoud en bijwerken van het model (en mogelijk de vectordatabase als on-prem) aan u. Met een zeer domeinspecifieke dataset en de expertise, kan een lokaal model worden aangepast om in dat domein uit te blinken, waardoor het een sterke oplossing is voor een "private GPT". Local Open-Source LLMs control and privacy Do van – Het gebruik van een API zoals OpenAI’s GPT-4 betekent dat je je geen zorgen hoeft te maken over het uitvoeren van het model; je stuurt gewoon je opdrachten naar hun service en krijgt de voltooiing. Dit is erg handig en geeft je meestal toegang tot geavanceerde modelkwaliteit zonder infrastructuurproblemen. Voor ons scenario kun je RAG gebruiken door simpelweg de gehaalde documenten voor te stellen aan je prompt en de API te vragen om te antwoorden. De nadelen hier hebben betrekking op aanpassing en privacy. Niet elk model is beschikbaar voor fijne aanpassing ( Je bent ook onderworpen aan de regels van de provider (bijvoorbeeld, ze kunnen inhoudsfilters hebben die sommige scraping-gerelateerde queries kunnen voorkomen).Vanuit een privacyperspectief stuurt u uw gegevens (query en gedownload context) naar een derde partij, dus ik zal deze aanpak niet voorstellen voor gevoelige of auteursrechtelijk beschermde gegevens. External API LLMs (e.g. OpenAI’s) OpenAI, bijvoorbeeld, kunt u het doen op GPT4-o en GPT4-mini OpenAI, bijvoorbeeld, kunt u het doen op GPT4-o en GPT4-mini Als je prioriteit de best mogelijke taalvaardigheid en snelle configuratie is, kan een gehost model zoals OpenAI's de betere keuze zijn. In de implementatie van dit bericht zullen we illustreren met behulp van OpenAI's GPT API voor eenvoud en kwaliteit, maar het opsporingssysteem dat we bouwen zou net zo gemakkelijk kunnen voeden in een open-source model zoals Llama2 via HuggingFace of LangChain bibliotheken. We zullen de RAG-benadering gebruiken met een OpenAI-model, dat goed overeenkomt met voortdurend bijgewerkte webgegevens en de noodzaak voor kostbare fijne-tuningjobs vermijdt. Scraping TWSC met Firecrawl is een web scraping engine blootgesteld als een REST API en SDK. Het is speciaal ontworpen om websites in (in formaten zoals schone tekst of markdown), omgaan met alle zware lifting, zoals crawlen links, rendering JavaScript, enzovoort. het grote voordeel van Firecrawl is dat met één API-oproep, u een hele site kunt scrapen. Firecrawl LLM-ready data Firecrawl Firecrawl Voor de blog van The Web Scraping Club zullen we de sitemap gebruiken om alle artikel-URL's te ontdekken. (De blog wordt gehost op Substack, die een XML-sitemap biedt waarin alle berichten worden vermeld.) Firecrawl kan de site zonder een sitemap crawlen, maar het gebruik ervan als uitgangspunt kan efficiënter zijn en ervoor zorgen dat we geen pagina's missen. Eerst instellen we Firecrawl door de Python SDK te installeren en te authenticeren met een API-sleutel (ter veronderstelling dat u zich hebt aangemeld en een sleutel hebt verkregen): from firecrawl import FirecrawlApp import os os.environ["FIRECRAWL_API_KEY"] = "YOURKEY" # or load from .env app = FirecrawlApp() # Define the sitemap URL (we can loop this for multiple years if needed) map_result = app.map_url('https://substack.thewebscraping.club/sitemap.xml', params={ 'includeSubdomains': True }) print(map_result) for article in map_result['links']: if '/p/' in article: print(article) response = app.scrape_url(url=article, params={'formats': [ 'markdown' ]}) Met slechts een paar regels code zijn onze artikelen al in Markdown-formaat. Een vectordatabase voor RAG kiezen a is een belangrijk onderdeel van de RAG-implementatie. Het slaat de embeddings van uw documenten op (vectorrepresentaties) en maakt een snelle vergelijkingszoekopdracht mogelijk om relevante documenten voor een bepaalde query-embedding op te halen. Veel opties zijn beschikbaar, waaronder open-source bibliotheken en beheerde clouddiensten, maar voor onze implementatie gebruiken we . vector database Pinecone is een In tegenstelling tot open source databases die zelfhosting vereisen, is Pinecone een cloud-native oplossing, wat betekent dat we ons geen zorgen hoeven te maken over infrastructuurbeheer. Pinecone fully managed vector database Pinecone Pinecone opzetten De eerste stappen zijn natuurlijk het aanmelden bij Pinecone en het krijgen van de API_KEY en omgeving van het dashboard. pip install pinecone Ten slotte kunnen we dan verbinding maken met Pinecone in ons script from pinecone import Pinecone, ServerlessSpec pc = pinecone.Pinecone( api_key="YOUR API KEY" ) De omgevingswaarde komt van de Pinecone webconsole wanneer u uw API-sleutel maakt. Een Pinecone Index maken Een index is waar uw gegevens worden opgeslagen voor een later retrivial van de LLM. In plaats van in eenvoudige tekst, is het in vectorformaat (in principe een reeks getallen), waardoor de LLM begrijpt welke entry in de index waarschijnlijker een goed antwoord is voor de query die de LLM maakt. In de a als , naast vectorgegevens, hebben we ook metadata: metadata is opgeslagen naast elke vector (embedding) om het terugvinden betekenisvoller te maken. vector database Pinecone, , or ChromaDB Weetjes extra information ChromaDB ChromaDB Weetjes Weetjes Terwijl vertegenwoordigen gebruikt voor vergelijkbaarheidsonderzoek, geeft gestructureerde informatie over wat de vector vertegenwoordigt. Terwijl we in de vectorgegevens de markering van de artikelen invoeren, zullen we in de metagegevens enkele informatie gebruiken die we willen dat de LLM met ons deelt, zoals de auteur van de blog die voor het antwoord werd gebruikt, de titel en de link naar de post. vectors numerical embeddings metadata filtering, categorization, and interpretability index_name = "article-index" if not pc.has_index(index_name): index_model = pc.create_index_for_model( name=index_name, cloud="aws", region="us-east-1", embed={ "model":"llama-text-embed-v2", "field_map":{"text": "chunk_text"} } ) #pc.describe_index(index_name) #to get the host index=pc.Index(host='YOURINDEXENDPOINT') ..... article_data = [ {"id": f"article-{i}", "text": page["markdown"], "url": page["metadata"]["url"], "title": page["metadata"]["title"], "author": page["metadata"]["author"][0]} for i, page in enumerate(scrape_results['data']) ] #print(article_data) # Generate embeddings using LLaMA v2 for article in article_data: # Estrai il testo dell'articolo text = article["text"] #print(text) # Single article insert to avoid failures embedding = pc.inference.embed( model="llama-text-embed-v2", inputs=[text], parameters={"input_type": "passage"} ) # Prepare data for Pinecone upsert vector_data = { "id": article["id"], # Unique article ID "values": embedding[0]["values"], # Embedding vector "metadata": { "url": article["url"], # Store article URL "content": text[:300], # Store first 500 chars as a preview/snippet "title": article["title"][:100], "author": article["author"][:50] } } #print(vector_data) # Upsert the single article into Pinecone index.upsert(vectors=[vector_data], namespace="articles") print(f"✅ Upserted: {article['id']} ({article['title']})") # Optional: Add a short delay to prevent API rate limits (adjust as needed) time.sleep(1) Zoals je uit de code kunt zien, herhalen we in principe elk artikel dat eerder is geschrapt en voegen we het toe aan een nieuw gecreëerde index genaamd . article-index Als je meer wilt spelen met Pinecone is er uitgebreide documentatie op hun website. uitgebreide documentatie op hun website. Maar nu ik alle artikelen op de index heb geplaatst, kunnen we de informatie extraheren die we nodig hebben? Ik heb een basis script genaamd query.py gemaakt om de resultaten van de zoekopdrachten op de index te testen. Wanneer gevraagd wordt "Kunt u alstublieft enkele artikelen over het omzeilen van Kasada vermelden?", geeft de query de volgende artikelen terug: {'matches': [{'id': 'article-0', 'metadata': {'author': 'Pierluigi Vinciguerra', ..., 'title': 'THE LAB #76: Bypassing Kasada With Open ' 'Source Tools In 2025', 'url': 'https://substack.thewebscraping.club/p/bypassing-kasada-2025-open-source'}, 'score': 0.419812053, 'values': []}, {'id': 'article-129', 'metadata': {'author': 'Pierluigi Vinciguerra', ..., 'title': 'How to by-pass Kasada bot mitigation?', 'url': 'https://substack.thewebscraping.club/p/how-to-by-pass-kasada-bot-mitigation'}, 'score': 0.418432325, 'values': []}, {'id': 'article-227', 'metadata': {'author': 'Pierluigi Vinciguerra', ..., 'title': 'Scraping Kasada protected websites', 'url': 'https://substack.thewebscraping.club/p/scraping-kasada-protected-websites'}, 'score': 0.378159761, 'values': []}], 'namespace': 'articles', 'usage': {'read_units': 6}} Niet slecht! alle drie de artikelen waren precies over het onderwerp! Voor vandaag is het genoeg, in de volgende aflevering zullen we zien hoe je deze DB kunt verbinden met GPT4 en vervolgens een eenvoudige gebruikersinterface kunt maken om opdrachten te schrijven en de gegevens te krijgen die je nodig hebt. Het artikel maakt deel uit van de “The Lab” serie door Pierluigi Vinciguerra. Bekijk zijn Substack pagina voor meer kennis over Web Scraping. Het artikel maakt deel uit van de “The Lab” serie door Pierluigi Vinciguerra. Bekijk zijn Substack pagina voor meer kennis over Web Scraping. ‘Het laboratorium’