langChain在我理解是一个集成了开发,测试,部署功能的一个llm大语言模型的框架
官方描述:
LangChain 是一个用于构建基于大型语言模型(LLM)应用的框架,旨在简化 LLM 的集成、增强其能力,并支持复杂交互。它由 Harrison Chase 开发,已成为 AI 应用开发的重要工具,尤其适用于需要结构化数据处理、多步推理和外部知识检索的场景。
在学习langchain的时候,你肯定已经了解过大模型并使用过基本的llm啦,接下来一起初步探究langchain
1,创建与大模型的对话
import os
from dotenv import load_dotenv
load_dotenv()
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "你叫当当,别人问你的时候,你 always 回复:当当,你叫什么名字?"),
("user","{input}")
])
print(prompt)
# 初始化模型
langchainModel = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# langchainModel = Tongyi(model="qwen-plus",api_key=os.getenv("DASHSCOPE_API_KEY"))
repose = langchainModel.invoke("你叫什么名字")
print(repose)
output_info = StrOutputParser()
chain = prompt | langchainModel | output_info
# repose = langchainModel.invoke("你叫什么名字")
repose = chain.invoke({"input": "你叫什么名字"})
print(repose)
1.与llm的区别PromptTemplate生成提示词模板 其中可以用{input} 注入值,最后用invoke调用填值, 2.其中涉及到一个 | 链式调用方法 把左边的值交给右边处理 prompt | langchainModel | output_info 就是把prompt提示词交给 langchainModel 创建好的大模型 最后交给output_info去处理返回值, 3.图中大模型创建方式也有所不同 区别就是 图中大模型的返回值会带有一些额外的信息,比如 token 的消耗量以及明细
2,下面一起做一个小项目
首先,需要创建文本向量处理方式 在非langchain代码中,我们是这样处理的client为初始化的llm
repose = client.embeddings.create(
model="text-embedding-v3",
input=text
).data
在langchain中,我是这样处理的
embeddings = OpenAIEmbeddings(
model="text-embedding-v3",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
这样报错了创建失败,网上查询得知
DashScope Embeddings 是阿里云推出的一款先进的文本嵌入服务,能够将文本转换为高质量的向量表示,广泛应用于自然语言处理(NLP)和机器学习任务,如文本分类、相似度计算和信息检索
如果使用阿里的框架必须要使用DashScope
embeddings = DashScopeEmbeddings(
model="text-embedding-v3", # 阿里云支持的模型
dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"),
)
这样就可以创建出来
联想一下如果这样,那么初始化大模型的代码是不是也需要测试一下两种创建方式
langchainModel = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
这个通过ChatOpenAI经过测试是可以正常使用的
那么用DashScope的创建方式呢
把ChatOpenAI替换成Tongyi就可以了也是可以正常使用的
利用这个向量处理来写代码如下
import requests
from bs4 import BeautifulSoup
import os
from dotenv import load_dotenv
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_core.documents import Document
load_dotenv()
#爬取数据
url = "https://www.shuzhaige.com/douluodalu/"
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}
# Send a GET request to the URL
res = requests.get(url, headers=header)
res.encoding = "utf-8"
documents = []
# Check if the request was successful
if res.status_code == 200:
# Parse the HTML content using BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
# Find all <li> elements with the class 'line3'
chapters = soup.find_all('li', class_='line3')
# Extract the chapter title and URL from each <li> element
documents = [chapter.find('a').get('title') for chapter in chapters]
else:
print(f"Failed to retrieve the webpage. Status code: {res.status_code}")
print(documents)
documents_list = [Document(page_content=title, metadata={"source": "斗罗大陆"}) for title in documents]
print(documents_list)
from langchain_openai import OpenAIEmbeddings
# embeddings = OpenAIEmbeddings(
# model="text-embedding-v3",
# api_key=os.getenv("DASHSCOPE_API_KEY"),
# base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
# )
embeddings = DashScopeEmbeddings(
model="text-embedding-v3", # 阿里云支持的模型
dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"),
)
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter =RecursiveCharacterTextSplitter(chunk_size=25, chunk_overlap=10)
texts = text_splitter.split_text(str(documents))
for text in texts:
print(text)
vector1 = FAISS.from_texts(texts, embeddings)
print(vector1)
texts = text_splitter.split_documents(documents_list)
print("texts",texts)
# vectorEmbedding = embeddings.embedding("hello")
# print(vectorEmbedding)
vector = FAISS.from_documents(texts, embeddings)
print(vector)
query = "唐三的第一魂技是什么?"
results = vector.similarity_search(query, k=5)
for result in results:
print(result.page_content)
RecursiveCharacterTextSplitter是langchain提供的一种文本滑动框切割方式 25 是每次切割多少字符,10是滑动保留几个字符
例如:如果这两个参是 3 2 的话 切割 123456 就是 123 234 456 。
RecursiveCharacterTextSplitter创建分割方式后调用split_text进行文本分割,最后FAISS.from_texts获得向量 代码中也使用了document
进入源码可以看到text 和 document的区别就是document 进行了一个封装 可以接收文档的集合源码如下
图中爬虫代码是自己写的,langchain也有爬虫框架,感兴趣可以自己了解一下我爬的数据只有斗罗大陆的目录
最后similarity_search查询的结果为
下面列举几个langchain常用的提示词模板内容很简单就不做解释了直接上代码
from langchain.prompts import PromptTemplate
prompt = "你叫当当,别人问你的时候,你 always 回复:当当,你叫什么名字?用户:{input}"
promptTemplate = PromptTemplate.from_template(prompt)
print(promptTemplate)
print("="*50)
print(promptTemplate.format(input="你叫什么名字?"))
from langchain.prompts import ChatPromptTemplate
sysMessage = "你叫{name1},别人问你的时候,你 always 回复:你叫什么名字,{name2}?"
humanMessage = "你叫什么名字{input}?"
prompt = ChatPromptTemplate.from_messages([
("system", sysMessage),
("user", humanMessage)
])
print(prompt)
print("="*50)
print(prompt.format(input="你叫什么名字?", name1="当当", name2="你"))
from langchain.prompts import ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate
sysTemplate = "你叫{name1},别人问你的时候,你 always 回复:你叫什么名字,{name2}?"
sysPrompt = SystemMessagePromptTemplate.from_template(sysTemplate)
humanTemplate = "你叫什么名字{input}?"
humanPrompt = HumanMessagePromptTemplate.from_template(humanTemplate)
prompt = ChatPromptTemplate.from_messages([sysPrompt,humanPrompt])
print(prompt)
print("="*50)
print(prompt.format(input="你叫什么名字?", name1="当当", name2="你"))
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
examples = [
{"input": "张三", "output": "张"},
{"input": "王强", "output": "王"},
{"input": "诸葛亮", "output": "诸葛"},
]
prompt_sample = "{input}性什么?{output}"
prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=PromptTemplate.from_template(prompt_sample),
suffix="{input}性什么?",
prefix="请根据输入的名字,给出姓。", # 取消注释以添加说明
input_variables=["input"]
)
print(prompt)
print("="*50)
print(prompt.format(input="刘备"))