AI(学习笔记第五课) 使用langchain进行AI开发 load documents(web)
文章目录
- 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
大模型给出了检索结果。