LangChain初探:为你的AI应用之旅导航

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介: 这篇文章带来了 LangChain 较为全面的精彩初探,带领小白选手轻松揭开其神秘面纱,一窥其独特之处。不容错过!

先来个温馨的小提醒:

这篇文章虽然较为全面地介绍了 LangChain,但都是点到为止,只是让你了解一下它的皮毛而已,适合小白选手。

So,如果你是 LangChain 的小白,看完之后还是一头雾水,那就请毫不留情地,狠狠地 .................................... 给我点赞吧!有了你的鼓励,我会再接再厉的!(ง •_•)ง

What?

丹尼尔:蛋兄,刚刚听到别人在说 LangChain,你知道是啥玩意吗?

蛋先生:哦,LangChain 啊,一个开发框架

丹尼尔:开发啥的框架?

蛋先生:一个用于开发语言模型驱动的应用的框架

丹尼尔:哦,开发这种应用,不就是写写 Prompt 提示语,调调语言模型 API 的事么?

蛋先生:没错。但 LangChain 使得 Prompt 的编写,API 的调用更加标准化

丹尼尔:就这样吗?

蛋先生:当然不止,它还有很多很酷的功能

丹尼尔:比如?

蛋先生:它可以连接外部数据源,根据输入检索相关数据作为上下文给到语言模型,使得语言模型可以回答训练数据之外的问题。这是由 LangChain 的 Retrieval 来实现的

丹尼尔:太酷了,我想到了一个场景,比如通过它来连接客服的回答话术库,这样就可以让语言模型摇身一变,变成一个专业的客服了

蛋先生:恩,这是一个很好的场景

丹尼尔:还有其它更酷的功能吗?

蛋先生:它可以让语言模型来自行决定采取哪些行动

丹尼尔:这个就不是很明白了

蛋先生:接着你那个客服的例子继续说。如果用户问的问题是关于公司产品的,我们就想让语言模型使用客服的话术库来回答;如果是其它问题,就让语言模型用它自己的知识来直接回答。如果是你,你会怎么实现?

丹尼尔:我想我会先通过语言模型来判断用户的问题是否关于公司产品。如果是,就走连接话术库的逻辑;如果不是,就走让语言模型直接回答的逻辑

蛋先生:恩,你这种就是 hardcode 逻辑的方式。还有一种更加 amazing 的 方式,就是让语言模型自行决定采取哪种行为。这个由 LangChain 的 Agent 来实现。

丹尼尔:听上去太酷了,怎么用呢?

蛋先生:莫急,待我慢慢道来

Why?

丹尼尔:蛋兄,你刚刚说到 LangChain 使得 Prompt 的编写,API 的调用更加标准化,标准化了肯定是好的,但好处很大吗?我用语言模型的 SDK 不也用得好好的吗?

蛋先生:那你先给一个使用 SDK 与语言模型交互的例子呗

丹尼尔:这还不简单,我就用这个吧:fireworks.ai (注:这个平台提供免费的资源,访问也方便)

from fireworks.client import Fireworks

client = Fireworks(api_key="<FIREWORKS_API_KEY>")
response = client.chat.completions.create(
  model="accounts/fireworks/models/llama-v2-7b-chat",
  messages=[{
   
   
    "role": "user",
    "content": "Who are you?",
  }],
)
print(response.choices[0].message.content)
输出:
Hello! I'm just an AI assistant, here to help you in any way I can. My purpose is to provide helpful and respectful responses, always being safe and socially unbiased. I'm here to assist you in a positive and ethical manner, and I'm happy to help you with any questions or tasks you may have. Is there anything specific you would like me to help you with?

蛋先生:很好,再给另外一个语言模型的例子呗

丹尼尔:额,一样的操作啊,你这是在消遣我吗?好吧,那我就再给一个百度的文心一言的例子

import os
import qianfan

os.environ["QIANFAN_AK"] = "<QIANFAN_AK>"
os.environ["QIANFAN_SK"] = "<QIANFAN_SK>"

chat_comp = qianfan.ChatCompletion()

resp = chat_comp.do(messages=[{
   
   
    "role": "user",
    "content": "Who are you?"
}])

print(resp.body['result'])
输出:
您好,我是百度研发的知识增强大语言模型,中文名是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。

蛋先生:Good,现在假设我一开始使用 fireworks 来开发应用,过程中发现效果不太理想,想换成文心一言呢?

丹尼尔:Oh~,各个语言模型的 SDK 的接口定义是不一样的,替换起来确实麻烦。来吧,是时候开始你的表演了

蛋先生:我们直接来看下通过 LangChain 使用 fireworks 和 文心一言 的代码示例吧,毕竟 No Code No BB 嘛

  • fireworks LangChain 示例
import os
from langchain_community.chat_models.fireworks import ChatFireworks

os.environ["FIREWORKS_API_KEY"] = '<FIREWORKS_API_KEY>'
model = ChatFireworks(model="accounts/fireworks/models/llama-v2-13b-chat")

res = model.invoke("Who are you?")
print(res.content)
  • 文心一言 LangChain 示例
import os
from langchain_community.chat_models import QianfanChatEndpoint

os.environ["QIANFAN_AK"] = "<QIANFAN_AK>"
os.environ["QIANFAN_SK"] = "<QIANFAN_SK>"
model = QianfanChatEndpoint(model="ERNIE-Bot-turbo")

res = model.invoke("Who are you?")
print(res.content)

丹尼尔:好像看出来了,标准化之后,要更换语言模型变得非常方便了,只需要更换下 model 的实例化就行了

蛋先生:是的,这只是个最简单的例子,LangChain 还有很多种优雅的方式来切换不同的模型。从此以后我们就可以专注于 Prompt 的开发了。语言模型嘛,哪个合适换哪个

How?

丹尼尔:好了,我决定入坑 LangChain 了,那咱们进一步聊聊?

蛋先生:当然可以!我们从简单到复杂,结合代码和流程图来展示 LangChain 的一些用法。先来最简单的代替 SDK 的用法,这个上边已经有提到了

res = model.invoke("tell me a short joke about a cat")
print(res.content)

image

丹尼尔:恩,这个 so easy,一瞄就懂

蛋先生:OK,那接下来我们来使用 PromptTemplate,通过变量的方式来控制模板里的部分内容

from langchain_core.prompts import ChatPromptTemplate

...

prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
chain = prompt | model
res = chain.invoke({
   
   "topic": "a cat"})
print(res.content)

image

丹尼尔:使用 PromptTemplate 的方式来写 prompt,确实比字符串的拼接要优雅不少

蛋先生:再加个简单的输出转换吧

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

...

prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
output_parser = StrOutputParser()
chain = prompt | model | output_parser
res = chain.invoke({
   
   "topic": "a cat"})
print(res)

image

丹尼尔:终于知道为啥叫 chain

蛋先生:继续?

丹尼尔:继续...

蛋先生:接下来这段代码可能有点长哦

from langchain_community.embeddings import QianfanEmbeddingsEndpoint
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import faiss
from langchain_community.chat_models import QianfanChatEndpoint

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains.combine_documents import create_stuff_documents_chain

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# 1
docs = WebBaseLoader("https://docs.smith.langchain.com").load()
embeddings = QianfanEmbeddingsEndpoint()
documents = RecursiveCharacterTextSplitter(chunk_size=900).split_documents(docs)
vector = faiss.FAISS.from_documents(documents, embeddings)
retriever = vector.as_retriever(search_kwargs={
   
   'k': 4})

# 2
setup_and_retrieval = RunnableParallel(
    {
   
   "context": retriever, "input": RunnablePassthrough()}
)
prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:
<context>
{context}
</context>
Question: {input}""")
model = QianfanChatEndpoint(streaming=False, model="ERNIE-Bot-turbo")
output_parser = StrOutputParser()

# 3
retrieval_chain = setup_and_retrieval | prompt | model | output_parser

res = retrieval_chain.invoke("how can langsmith help with testing?")
print(res)

丹尼尔:请把“可能”去掉,谢谢

蛋先生:但逻辑其实并不复杂,主要分为三块

1)加载网页文档,通过 Embeddings 将文档内容转成向量并存储在向量数据库 FAISS 中,retriever 就是一个可以根据输入从向量数据库获取相关文档的检索工具

2)声明 chain 的各个步骤

3)将各个步骤按顺序 chain 起来

丹尼尔:等等,看着有点脑壳疼。Embeddings?向量?向量数据库?

蛋先生:咱们今天是“初探”,所以也只能简单讲讲,不然很多同学就要昏昏欲睡了

丹尼尔:没问题,有个大概印象也好

蛋先生:首先,为什么要将文本转成向量呢?因为通过计算两个向量的距离,我们就可以量化地评估它们的相关性。距离越小,通常意味着文本之间的相关性越高。我们这里是需要检索与输入相关的文档内容,将其作为会话上下文提供给语言模型。如果是整个文档都传过去,是不是就太大了呢?

丹尼尔:哦,原来向量有这么高级的功能啊

蛋先生:没错。然后要将文本转成向量,就需要用到 Embeddings(词嵌入)技术。Embeddings 在历史上有过多种方法,如基于统计的计数方法,基于神经网络的推理方法等。 QianfanEmbeddingsEndpoint 正是一个利用深度学习训练得到的 Embeddings 模型服务,输入为文本,输出为向量

丹尼尔:大概有点明白了

蛋先生:那我们接着看下流程图

image

丹尼尔:能否为小弟我解释一下上面这个流程图的前半部分

蛋先生:当然!首先输入是 "how can langsmith help with testing?";接着有个并行的逻辑,一个是通过 Retriever 根据输入检索相关的文档内容作为 context 的值,另一个则是直接 pass 将输入作为 input 的值;然后就是将数据传给 Prompt 模板,最终就可以得到传给语言模型的 PromptValue 了

丹尼尔:Soga

蛋先生:注意,压轴要登场了哦,现在让我们来请出大名鼎鼎的 Agent 吧

from langchain import hub
from langchain.agents import AgentExecutor, create_json_chat_agent
from langchain.tools import tool
from langchain_community.chat_models.fireworks import ChatFireworks

@tool
def leng(word: str) -> str:
    """Please use this tool if you want to find the length of the word."""
    return len(word)
@tool
def lower(word: str) -> str:
    """Please use this tool if you need to change the word to lowercase."""
    return f'dx_{word.lower()}'


tools = [leng, lower]
model = ChatFireworks(model="accounts/fireworks/models/llama-v2-70b-chat")
prompt = hub.pull("hwchase17/react-chat-json")

agent = create_json_chat_agent(model, tools, prompt, stop_sequence=False)
agent_executor = AgentExecutor(
    agent=agent, tools=tools, verbose=True, handle_parsing_errors=True, max_iterations=5)

res = agent_executor.invoke({
   
   "input": "Make this word lowercase: 'Daniel'"})
print(res)
{
   
   'input': "Make this word lowercase: 'Daniel'", 'output': "The lowercase version of 'Daniel' is 'dx_daniel'"}

丹尼尔:好耶,快点讲解一下吧

蛋先生:首先我们声明了两个工具:一个是 leng(用于求字符串长度),一个是 lower(用于将字符串变成小写)。这里为了证明结果是通过我们的工具来得到结果的,所以特意在 lower 的实现中加了个 dx_ 前缀

丹尼尔:等等,hub.pull("hwchase17/react-chat-json") 是什么神秘代码?

蛋先生:这是 LangChain hub 社区上共享的用于实现 Agent 的众多 Prompt 中的一个,你可以在这里找到很多有用的 Prompt。毕竟,语言工程也是一种艺术,也是需要实践积累的。

丹尼尔:明白,请继续

蛋先生:通过 Agent,语言模型就可以根据输入自行判断应该使用哪个工具了

丹尼尔:哇,这太神奇了!我对它是怎么自行判断很感兴趣

蛋先生:简单来说,语言模型可以根据输入,再根据各个工具的描述,来判断哪个工具更适合,然后将结果输出为可以让 LangChain 理解的执行指令(比如 JSON)

丹尼尔:太棒了!现在我对 LangChain 有了一个大致的了解,希望以后还能跟你继续深入探讨

蛋先生:机会有滴是,咱们后会有期!ヾ( ̄▽ ̄)Bye~Bye~

相关实践学习
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
目录
相关文章
|
1天前
|
机器学习/深度学习 人工智能 搜索推荐
AI技术在医疗诊断中的应用
【7月更文挑战第3天】随着科技的不断进步,人工智能(AI)技术在各个领域的应用越来越广泛。特别是在医疗领域,AI技术的应用为医生提供了更加准确、高效的诊断工具,从而提高了患者的治疗效果和生活质量。本文将探讨AI技术在医疗诊断中的应用,包括影像诊断、基因检测、病理分析等方面,并展望AI技术在未来医疗领域的发展前景。
|
3天前
|
机器学习/深度学习 人工智能 算法
AI技术在医疗领域的应用与挑战
【6月更文挑战第30天】本文将探讨AI技术在医疗领域的应用及其面临的挑战。随着科技的进步,AI技术已经在医疗领域取得了显著的成果,如辅助诊断、疾病预测等。然而,AI技术在医疗领域的应用也面临着数据隐私、算法偏见等挑战。本文将详细分析这些问题,并探讨如何克服这些挑战,以实现AI技术在医疗领域的更好应用。
|
1天前
|
人工智能 自然语言处理 小程序
政务VR导航:跨界融合AI人工智能与大数据分析,打造全方位智能政务服务
政务大厅引入智能导航系统,解决寻路难、指引不足及咨询台压力大的问题。VR导视与AI助手提供在线预览、VR路线指引、智能客服和小程序服务,提高办事效率,减轻咨询台工作,优化群众体验,塑造智慧政务形象。通过线上线下结合,实现政务服务的高效便民。
16 0
政务VR导航:跨界融合AI人工智能与大数据分析,打造全方位智能政务服务
|
5天前
|
机器学习/深度学习 人工智能 运维
智能化运维:AI在IT管理中的应用与挑战
【6月更文挑战第28天】随着人工智能技术的飞速发展,其在IT运维领域的应用逐渐深入。本文将探讨AI技术在智能化运维中的角色,包括自动化故障诊断、预测性维护、以及安全监控等方面。同时,我们也将分析实施智能化运维时面临的技术挑战和伦理问题,旨在为读者提供一个关于如何有效整合AI技术进入IT运维实践的全面视角。
|
6天前
|
机器学习/深度学习 人工智能 监控
AI在医疗领域的应用?
【6月更文挑战第28天】AI在医疗领域的应用?
62 1
|
6天前
|
机器学习/深度学习 人工智能 监控
AI在金融领域的应用
【6月更文挑战第28天】AI在金融领域的应用
58 1
|
1天前
|
人工智能 监控 安全
未来智能城市中的AI技术应用与挑战
在未来智能城市的构想中,人工智能(AI)技术将扮演关键角色,从交通管理到资源分配,再到市民生活的各个方面。本文探讨了AI在智能城市中的广泛应用及其带来的挑战,重点分析了数据隐私保护、系统安全性和社会接受度等方面的问题。 7月更文挑战第1天
|
1天前
|
机器学习/深度学习 人工智能 自然语言处理
未来智能交互:AI技术的进展与应用展望
随着人工智能(AI)技术的迅猛发展,智能交互系统正逐步成为日常生活和工作中不可或缺的一部分。本文探讨了AI技术在智能交互领域的最新进展,以及未来可能的应用前景,涵盖了语音识别、自然语言处理和智能助理等关键技术的演进与应用案例。 7月更文挑战第1天
14 0
|
2天前
|
机器学习/深度学习 人工智能 算法
AI技术在医疗领域的应用与挑战
【7月更文挑战第2天】人工智能技术在医疗领域的应用正日益广泛,从疾病诊断到治疗方案的制定,再到患者管理和医疗服务的优化,AI的应用正在逐步改变着医疗行业的面貌。然而,随着AI技术的深入应用,也带来了一系列挑战,如数据隐私保护、算法透明度和公平性等问题。本文将探讨AI在医疗领域的应用现状,分析其面临的主要挑战,并提出相应的解决策略。
|
5天前
|
机器学习/深度学习 人工智能 搜索推荐
AI在医疗领域的应用及其前景
【6月更文挑战第28天】随着科技的不断发展,人工智能(AI)已经在各个领域取得了显著的成果。特别是在医疗领域,AI的应用已经从辅助诊断、疾病预测、药物研发等方面展现出了巨大的潜力和价值。本文将深入探讨AI在医疗领域的应用及其前景,以期为相关领域的研究和应用提供参考。