文章目錄
- AI(學習筆記第五課) 使用langchain進行AI開發 load documents(web)
- 學習內容:
- 1.load documents(web)
- 1.1 學習`url`
- 1.2 提前安裝`python`的`package`
- 1.2 使用`WebBaseLoader`進行`webpage`的`load`
- 1.3 使用`BeautifulSoup4`進行`webpage`的部分截取
- 1.4 使用`UnstructuredURLLoader`的部分截取
- 1.5 使用`UnstructuredULoader`的截取父子關系的節點
- 1.5.1 使用時候的注意點
- 1.5.2 代碼解析
- 1.5.3 代碼執行
- 2. 使用定位結果進行檢索`Vector search over page content`
- 2.1 最終代碼
- 2.2 執行結果
AI(學習筆記第五課) 使用langchain進行AI開發 load documents(web)
- 使用
langchain
如何解析web page
- 使用
vector_store
對search
的docs
進行ai
檢索
學習內容:
- 從
webpage
中構建vector store
,并使用進行檢索
1.load documents(web)
1.1 學習url
langchain的load documents(web)文檔。
1.2 提前安裝python
的package
langchain-community
beautifulsoup4
langchain_core
1.2 使用WebBaseLoader
進行webpage
的load
import asyncio
import bs4,os
from langchain_community.document_loaders import WebBaseLoader, UnstructuredURLLoader
from typing import List
from langchain_core.documents import Document
page_url = "https://python.langchain.com/docs/how_to/chatbots_memory/"
# 設置USER_AGENT避免警告
os.environ["USER_AGENT"] = "MyApp/1.0"
async def load_whole_web():loader = WebBaseLoader(web_paths=[page_url])pages = []async for page in loader.alazy_load():pages.append(page)print(f"{pages[0].metadata}\n")print(pages[0].page_content[:500].strip())asyncio.run(load_whole_web())
這里,使用WebBaseLoader
對代碼對指定的webpage
進行load
到pages
變量中,之后使用metadata
和page_content
進行輸出。
metadata
輸出如下json
1.3 使用BeautifulSoup4
進行webpage
的部分截取
實際上,很可能需要對特定的<div>
或者特定的class
,來對特定的webpage
部分進行截取。
async def load_partial_web():loader = WebBaseLoader(web_paths=[page_url],bs_kwargs={"parse_only": bs4.SoupStrainer(class_="theme-doc-markdown markdown"),},bs_get_text_kwargs={"separator": " | ", "strip": True},)docs = []async for doc in loader.alazy_load():docs.append(doc)assert len(docs) == 1doc = docs[0]print(f"{doc.metadata}\n")print(doc.page_content[:500])print(doc.page_content[-500:])
asyncio.run(load_partial_web())
這樣保證,截取的是<div class="theme-doc-markdown markdown">
的部分。
1.4 使用UnstructuredURLLoader
的部分截取
和pdf
的loader
一樣,想要對內容進行洗的切分,可以使用UnstructuredURLLoader
。
注意,這里練習時候使用的UnstructuredURLLoader
的版本較低,對示例的代碼進行了調整。
async def load_web_with_unstructured():loader = UnstructuredURLLoader(urls=[page_url], # 替換為實際URLmode="elements",strategy='fast')docs = []async for doc in loader.alazy_load():docs.append(doc)for doc in docs[:5]:print(f'{doc.metadata["category"]}: {doc.page_content}')return docsasyncio.run(load_web_with_unstructured())
可以看出,這里將web
內容解析到doc
中,保存起來,并將前5個doc
進行category
和page_content
進行打印。
1.5 使用UnstructuredULoader
的截取父子關系的節點
1.5.1 使用時候的注意點
這里需要注意兩點:
- 不是
from langchain_community.document_loader
的UnstructuredURLLoader
,這里需要換成from langchain_unstructure的
UnstructuredLoader` langchain_unstructured
的包,版本需要>=0.1.5
1.5.2 代碼解析
import asyncio
import bs4,os
from langchain_community.document_loaders import WebBaseLoader,UnstructuredURLLoader
from langchain_unstructured import UnstructuredLoader
from typing import List
from langchain_core.documents import Document
async def get_setup_docs():page_urls = ["https://python.langchain.com/docs/how_to/chatbots_memory/","https://python.langchain.com/docs/how_to/chatbots_tools/",]setup_docs = []for url in page_urls:page_setup_docs = await _get_setup_docs_from_url(url)setup_docs.extend(page_setup_docs)for doc in setup_docs[:3]:print(f'{doc.metadata["category"]}: {doc.page_content}')return setup_docsasync def _get_setup_docs_from_url(url: str) -> List[Document]:loader = UnstructuredLoader(web_url=url)setup_docs = []parent_id = -1async for doc in loader.alazy_load():metadata = doc.metadataif metadata.get("category") == "Title" and doc.page_content.startswith("Setup"):parent_id = metadata.get("element_id")if metadata.get("parent_id") == parent_id:setup_docs.append(doc)return setup_docsasyncio.run(get_setup_docs())
這里,可以看出是定位到category
==Title
并且startWith(Setup)
的部分,之后記錄下parent_id
,之后接下來便利其他doc
,如果parent_id
是上面記錄的parent_id
那么就將該doc
都作為setup
的說明文檔,保存起來。
1.5.3 代碼執行
2. 使用定位結果進行檢索Vector search over page content
2.1 最終代碼
import asyncio
import bs4,os
from langchain_community.document_loaders import WebBaseLoader,UnstructuredURLLoader
from langchain_unstructured import UnstructuredLoader
from typing import List
from langchain_core.documents import Document
from langchain_ollama.embeddings import OllamaEmbeddings
from langchain_core.vectorstores import InMemoryVectorStorepage_url = "https://python.langchain.com/docs/how_to/chatbots_memory/"
# 設置USER_AGENT避免警告
os.environ["USER_AGENT"] = "MyApp/1.0"# 替換 OpenAIEmbeddings 配置為 Ollama 本地模型
embeddings = OllamaEmbeddings(model="nomic-embed-text", # 或其他支持的本地模型如 "mistral", "nomic-embed-text"base_url="http://192.168.2.208:11434" # Ollama 默認地址
)
async def _get_setup_docs() -> List[Document]:page_urls = ["https://python.langchain.com/docs/how_to/chatbots_memory/","https://python.langchain.com/docs/how_to/chatbots_tools/",]setup_docs = []for url in page_urls:page_setup_docs = await _get_setup_docs_from_url(url)setup_docs.extend(page_setup_docs)return setup_docsasync def _get_setup_docs_from_url(url: str) -> List[Document]:loader = UnstructuredLoader(web_url=url)setup_docs = []parent_id = -1async for doc in loader.alazy_load():metadata = doc.metadataif metadata.get("category") == "Title" and doc.page_content.startswith("Setup"):parent_id = metadata.get("element_id")if metadata.get("parent_id") == parent_id:setup_docs.append(doc)return setup_docsasync def search_vector_store():setup_docs =await _get_setup_docs()vector_store = InMemoryVectorStore.from_documents(setup_docs, embeddings)retrieved_docs = vector_store.similarity_search("Install Tavily", k=2)for doc in retrieved_docs:print(f'Page {doc.metadata["url"]}: {doc.page_content[:300]}\n')asyncio.run(search_vector_store())
這里看出,使用本地構建的ollama
模型nomic-embed-text
,進行ai
的檢索。
2.2 執行結果
基于webpage
,ai
大模型給出了檢索結果。