最近做了一个笔试,内容是使用langchain构建一个关于公司用户手册的问答机器人,并给出了参考代码。
笔试需求只有获取信息部分有所不同。参考代码中是读取了sitemap.xml文件,获取其中所有url,再写一个获取url对应博客文本信息的函数,而需求是用zendesk的API读取json文件来获取里面的url。下面直接上代码,:
- create_embedding.py
import os
import cloudscraper
import requests
from bs4 import BeautifulSoup
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
import pickle
# 设置访问令牌和URL
access_token = 'oPzVt7pyQy7o44RXR4SxR1AL'
url = 'https://support.strikingly.com/api/v2/help_center/en-us/articles.json'
# 发送 API 请求并获取响应
headers = {
'Authorization': 'Bearer {}'.format(access_token),
'Content-Type': 'application/json'
}
response = requests.get(url, headers=headers)
pages = []
# 处理 API 响应
if response.status_code == 200:
data = response.json()
html_urls = [article['html_url'] for article in data['articles'] if 'html_url' in article]
# 输出或处理 html_urls 列表
for url in html_urls:
print(url)
pages.append({'text': extract_text_from(url), 'source': url})
else:
print(f'Error: {response.status_code} - {response.text}')
首先需要设置Zendesk的令牌与包含url的json文件,调用requests函数访问json文件信息,然后依次把每个article中键为’html_url‘的值取出来放到pages数组里。接着遍历url,利用extract_text_from()函数获取url里的纯文本信息,extract_text_from()函数下面给出:
def extract_text_from(url):
'''
从给定的url里获取所有文本信息
:param url:
:return:
'''
# 采用cloudscraper来绕过cloudflare
scraper = cloudscraper.create_scraper(browser={
'browser': 'firefox',
'platform': 'windows',
'mobile': False
})
html = scraper.get(url).text
soup = BeautifulSoup(html, features="html.parser")
text = soup.get_text()
lines = (line.strip() for line in text.splitlines())
return '\n'.join(line for line in lines if line)
由于访问的url需要翻出去,没有用cloudscraper前直接用requests获取的是“please stand by…”,根本访问不了信息,所有百度了一下,使用cloudscraper可以解决此问题。
文本拆分并放入embedding api里去(直接复制粘贴博客代码):
# 每700个字符为一块,将所有文本分成块存放在docs里,metadata对应每个doc[[]]的地址
text_splitter = CharacterTextSplitter(chunk_size=700, separator="\n")
docs, metadatas = [], []
for page in pages:
splits = text_splitter.split_text(page['text'])
docs.extend(splits)
metadatas.extend([{"source": page['source']}] * len(splits))
print(f"Split {page['source']} into {len(splits)} chunks")
# 将上述内容放进嵌入向量,并存储为向量存储库。
store = FAISS.from_texts(docs, OpenAIEmbeddings(), metadatas=metadatas)
with open("stringly.pkl", "wb") as f:
pickle.dump(store, f)
- ask_question.py
把生成的向量库放到openai的API里(需要获取openai的令牌):
import os
from langchain import OpenAI
from langchain.chains import VectorDBQAWithSourcesChain
import pickle
import argparse
parser = argparse.ArgumentParser(description='Paepper.com Q&A')
parser.add_argument('question', type=str, help='Your question for Paepper.com')
args = parser.parse_args()
os.environ["OPENAI_API_KEY"]="sk-ZTmU2Jn9T3BlbkFJeoRiTD61huSxJl4hhoNF"
with open("stringly.pkl", "rb") as f:
store = pickle.load(f)
chain = VectorDBQAWithSourcesChain.from_llm(
llm=OpenAI(temperature=0), vectorstore=store)
result = chain({"question": args.question})
print(f"Answer: {result['answer']}")
print(f"Sources: {result['sources']}")
到此代码写完,下面是提问环节:python aks_question.py "xxxxxxxxxxx"
,回车即可输出答案和答案来源网址。
思考:这里是将公司的用户手册内容全部喂进openai,除此以外还有很多其他文本信息可以投入,日记、笔记、书籍等各种文本材料,投入openai后,AI即可回答与你投入信息相关的内容,成为一个能够自定义的AI。
参考:https://www.paepper.com/blog/posts/build-q-and-a-bot-of-your-website-using-langchain/