あなたがウェブデータを使用している会社で働いている場合、あなたは確実にそれがより複雑な製品の最初の層であることを知っています。実際、ウェブスクラップされたデータは、伝統的にファイルやデータベース(クラウドストレージボックス、データレイク、またはデータストア)に保存され、ビジネスインテリジェンス(BI)ツールを使用して分析され、商業的および独占的です。例えば、チームは製品価格や顧客レビューをウェブからスクラップし、原始データをCSV/JSONファイルとして保存し、SQLデータストアにロードし、TableauやPower BIのようなBIプラットフォームを使用してダッシュボードやレポートを作成します。現代のウェブスクラップソリューションは、構造化された形式(CSV、JSON、Excel 今日、大規模な言語モデル(LLMs)はこのパラダイムを変えています。静的ダッシュボードやSQLクエリにのみ依存するのではなく、組織はAIアシスタントを使用して、自然言語のプロンプトを通じて削除されたデータから洞察を得ることができます。言い換えれば、人間がクエリを書くことやグラフを解釈するのではなく、AIアシスタントは直接データに関する質問に答えることができます。あなたのChatGPTのようなインターフェイスを持つことについて考えて、ダッシュボードの作成を回避して洞察を得るためにいくつかのプロンプトを書くことができます。私はLLMが登場する前に、いくつかの製品でこのようなアプローチを見たが、大成功ではなかった。AIの進化とLLMで見られる毎週の と尋ねると、 このアプローチは、構築図やコードを書くことなく、非技術的なユーザーのためのより迅速で直感的な情報へのアクセスを約束します。 「上半期の価格が最も高い競争相手は誰ですか?」 もちろん、新たな挑戦が起こります:幻覚についてどうでしょうか? 答えの根底にある数字が見えなければ、答えが正しいと100%確信できますか? この記事(そしてラボシリーズの次の記事)では、このニュースレターの記事をスキャンし、AIの使用に適したデータベースに置き、この知識を取得し、GPTモデルの豊富なバージョンを使用できるウェブアプリケーションを公開することから始めます。 LLM知識の向上 LLMにカスタムデータ(クロスされたデータセットのような)を統合することは、主に2つの方法で行うことができます。 モデルまたは使用 , and each of these methods has pros and cons. Let's see how they differ and which approach could be the best for our use case. これらの方法のそれぞれに利点と欠点があります。 fine-tuning Retrieval-Augmented Generation (RAG) 「Fine-Tuning vs. Retrieval-Augmented Generation」 基本的に、あなたは事前に訓練されたモデルを取って、あなたのドメイン特有のデータセットでそれを訓練し、その重量を調整してその知識を組み込むことを意味します。例えば、あなたが技術的な記事のコレクションを削除した場合、あなたはそれらの記事にLLMを調節することができます。 Fine-tuning はしばしば、モデルにあなたのデータから質問と回答のカップルの大きなセットまたはテキストの段落を提供することによって行われるので、モデルは適切なときにその情報で応答することを学びます。 次にモデルをクエリするときは、外部の助けを必要とせずに、この調理された情報に基づくことができます。 Fine-tuning intrinsically knows augmented from the inside モデルは変わらないが、外部の知識ベースへのアクセス(通常はベクトル検索を介して)を与える。 あなたのデータからそれらをモデルに送信し、質問とともにLLMはその補足的文脈の助けを借りてその答えを生成します。私のようなブーマーにとっては、新しいスキルや動きを学ぶためにMatrixのネオの頭にCDを挿入するように考えてください。私たちのケースでは、知識ベースは、専門データベースに格納されたスクラップされたウェブ記事のコレクションかもしれません。RAGはLLMのオープンブック試験のようなものです - クエリタイムでは、データの関連する「ページ」を見上げて、内部メモリに頼るのではなく、答えを書くために使用します。 Retrieval-Augmented Generation (RAG) retrieve relevant documents あなたが想像できるように、ひとつの重要な違いは、追加的な知識がどこに留まっているかです: 細かい調節で、知識は埋め込まれています。 (モデルの重量が更新されています) RAG では、知識が残ります。 Fine-tuning はモデルに新しい事実を永久に教えるのに似ていますが、RAG はモデルに動的ライブラリを装備するようなものです。 in the model itself external この2つのアプローチには異なる利点と欠点があります: 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: 要するに、細かい調整は焦点を当てた理解に役立ちますが、RAGは知識へのリアルタイムアクセスを可能にします。RAGは、絶え間なく更新されたクロックデータを統合するための使用例として、モジュール全体を定期的にトレーニングするのではなく、継続的に新しいウェブデータを引っ張り、アシスタントに直ちに使用することができます。 進む前に、フィンタリングとRAGは相互に排他的ではないことに留意する価値があります;彼らは互いに補完することができます. たとえば、あなたはモデルをフィンタリングして、そのトーンや指示に従う能力を調整する (または小さく静的である知識を追加する) と、それでもRAGを使用して、頻繁に更新するより大きな知識ベースにアクセスすることができます。 ローカルモデル vs. External API もう一つの考慮点は あなたのAIアシスタントのために:あなた自身で実行するローカル(オープンソース)モデルまたはAPI(OpenAIのGPT-3.5/GPT-4またはその他)を介してホストされたモデルです。 what LLM to use – LLaMA 2、Mistral、またはFalconのようなモデルは、独自のサーバー上で実行することができます。 あなたのクロックされたデータは決してあなたの環境を離れることはありません、それは敏感な情報が含まれている場合に重要です。 あなたは自由にデータにそれらを調節したり、それらの働き方を変更することができます。 コスト面で、ローカルモデルを実行することは、大量のクエリ(API料金なし)のためにより安いかもしれないが、あなたはハードウェアまたはクラウドインフラストラクチャに投資する必要があります。 欠点は、多くのオープンモデルが最新のGPTのパフォーマンスに匹敵することができないことです。 あなたは比較可能なパフォーマンスを得るために、より大きなまたはより専門的なモデルを使用する必要があるかもしれません。 高度にドメイン特有のデータセットと専門知識を備え、ローカルモデルは、そのドメインで優れているように、強力な「プライベートGPT」ソリューションになります。 Local Open-Source LLMs control and privacy ドー – OpenAIのGPT-4のようなAPIを使用すると、モデルを実行することを心配する必要はありません。あなたは彼らのサービスにプロンプトを送信し、完了を取得するだけです。これは非常に便利で、通常、インフラのトラブルなしで最先端のモデル品質へのアクセスを提供します。私たちのシナリオのために、あなたは単にリクエストされたドキュメントをプロンプトに預け、APIに答えを求めてRAGを使用することができます。ここでの欠点はカスタマイズとプライバシーに関連しています。 あなたはまた、プロバイダーのルールに従う(例えば、いくつかのスキャン関連のクエリを防止するコンテンツフィルターを持っている可能性があります)。プライバシーの観点から、あなたはあなたのデータ(クエリと検索されたコンテキスト)を第三者に送信しているので、私は敏感なまたは著作権のデータのためのこのアプローチを提案しないでしょう。 External API LLMs (e.g. OpenAI’s) たとえば、OpenAIは、GPT4-oとGPT4-miniでそれを行うことを可能にします。 たとえば、OpenAIは、GPT4-oとGPT4-miniでそれを行うことを可能にします。 一般的に、あなたの使用ケースが非常に敏感なデータを含む場合や完全な制御を必要とする場合、追加の努力にもかかわらず、ローカルLLMが推奨されます。あなたの優先順位が可能な最高の言語能力と迅速なセットアップである場合、OpenAIのようなホストモデルはより良い選択肢かもしれません。この投稿の実装では、OpenAIのGPT APIを使用してシンプルさと品質を示しますが、私たちが構築したリクエストシステムは、HuggingFaceやLangChainライブラリを通じてLlama2のようなオープンソースモデルに簡単に供給することができます。リクエストメカニズム(ベクトルデータベース +類似性検索)は同じです。 これらの決定を考慮に入れて、私の削除された記事をAIアシスタントに統合しましょう. We will use the RAG approach with an OpenAI model, which aligns well with continuously updated web data and avoids the need for costly fine-tuning jobs. 私たちはOpenAIモデルとRAGアプローチを使用し、継続的に更新されているWebデータとよく一致し、コストがかかる細かい調整の仕事を回避します。 TWSC Scraping with Firecrawl(FirecrawlでTWSCをスキャンする) REST API と SDK として公開されているウェブスクラップエンジンです. It is specifically designed to turn websites into REST API and SDK. (クリーンテキストやマークダウンなどのフォーマットで)、クロールリンク、JavaScriptのレンダリングなど、すべての重いリフトを処理します。Firecrawlの大きな利点は、1回のAPI呼び出しで、サイト全体をスクラップすることができます。 花火 LLM-ready data 花火 花火 The Web Scraping Clubのブログでは、サイトマップを使用してすべての記事のURLを発見します(ブログはSubstackでホストされ、すべての投稿をリストするXMLサイトマップを提供しています)。 まず、Python SDK をインストールし、API キーで認証することによって Firecrawl を設定します(サインインしてキーを取得したと仮定します)。 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' ]}) わずか数行のコードで、私たちの記事はすでにMarkdown形式です。 RAG の Vector Database を選択する A RAG 実装の重要なコンポーネントです. ドキュメントの埋め込み (ベクトル表示) を保存し、迅速な類似性検索を可能にし、特定のクエリの埋め込みのための関連ドキュメントを取得します. オープンソースのライブラリやマネージドクラウドサービスを含む多くのオプションが利用可能ですが、当社の実装では、 . vector database Pinecone A は 自動ホスティングを必要とするオープンソースデータベースとは異なり、Pineconeはクラウドネイティブソリューションで、インフラストラクチャ管理について心配する必要はありません。 ピネコ fully managed vector database ピネコ Pineconeの設定 最初のステップは、もちろんPineconeにサインアップし、ダッシュボードからAPI_KEYと環境を取得することです。その後、いつものようにPython SDKをインストールできます。 pip install pinecone 最後に、私たちは私たちのスクリプトでPineconeに接続することができます。 from pinecone import Pinecone, ServerlessSpec pc = pinecone.Pinecone( api_key="YOUR API KEY" ) 環境値は、API キーを作成するときに Pinecone Web コンソールから入力されます。 Pinecone Indexの作成 インデックスは、あなたのデータがLLMから後のリトリビューションのために保存されている場所です. 単純なテキストではなく、それはベクトル形式(基本的に数列)で、LLMがどのインデックスの入力がLLMが作成するクエリの良い答えである可能性が高いことを理解することができます。 A で まるで , ベクトルデータに加えて、我々はまたメタデータを持っています:メタデータは それぞれのベクトル(埋め込み)と共に保存され、リサイクルをより有意義にする。 vector database Pinecone, , or ChromaDB ワイワイ extra information ChromaDB ChromaDB ワイワイ ワイワイ たとえ 代表 類似性の検索に使われ、 ベクターが何を表すかについての構造化された情報を提供します。 ベクターデータでは、記事のマークダウンを挿入しますが、メタデータでは、LLMが回答に使用したブログの著者、タイトル、投稿へのリンクなど、私たちと共有することを望むいくつかの情報を使用します。 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) あなたがコードから見ることができるように、我々は基本的に以前から削除されたすべての記事を繰り返し、これを新しく作成されたインデックスに追加します。 . article-index Pineconeでもっと遊びたいなら、 彼らのウェブサイトで広範囲にわたるドキュメンタリー。 彼らのウェブサイトで広範囲にわたるドキュメンタリー。 しかし、インデックスにすべての記事を挿入した今、私たちは必要な情報を抽出できますか? 私はquery.pyと呼ばれる基本的なスクリプトを作成し、インデックス上の検索結果をテストしました。 「カサダを乗り越えることについていくつかの記事を挙げることができますか?」と尋ねられると、以下の記事が返されます。 {'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}} 悪くない!この3つの記事はまさにそのテーマでした! 今日はそれで十分ですが、次のエピソードでは、このDBをGPT4に接続して、必要なデータを取得するためのシンプルなユーザーインターフェイスを作成する方法を見ていきます。 この記事は、Pierluigi Vinciguerraによる「The Lab」シリーズの一部です。Web Scrapingに関するより多くの知識のための彼のサブスタックページをご覧ください。 この記事は、Pierluigi Vinciguerraによる「The Lab」シリーズの一部です。Web Scrapingに関するより多くの知識のための彼のサブスタックページをご覧ください。 「ラボ」