LangChain Cookbook Part 2

参考自https://github.com/gkamradt/langchain-tutorials/blob/main/LangChain%20Cookbook%20Part%201%20-%20Fundamentals.ipynb

LangChain食谱-2

这个文档基于LangChain Conceptual Documentation

主要用例

  • 总结 - 表达有关文本或聊天交互的最重要事实
  • 文档问答 - 使用文档中保存的信息来回答问题或查询
  • 提取 - 从文本或用户查询中提取结构化数据
  • 评估 - 了解应用程序输出的质量
  • 查询表格数据 - 从数据库或其他表格源中提取数据
  • 代码理解 - 推理和消化代码
  • 与 API 交互 - 查询 API 并与外界交互
  • 聊天机器人 - 与用户进行来回交互的框架,结合聊天界面中的记忆
  • 代理 - 使用 LLM 来决定下一步做什么。使用工具实现这些决策。
    前往 LangChain 项目库查看这些用例的实例
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
# 如果要使显示屏更宽,请运行此单元
from IPython.display import display, HTML
display(HTML("<style>.container { width:90% !important; }</style>"))

LangChain 使用案例

Summarization(摘要)

LangChain 和 LLM 最常见的用例之一是摘要。您可以总结任何一段文本,但用例范围从总结通话、文章、书籍、学术论文、法律文件、用户历史记录、表格或财务文件。拥有一个可以快速总结信息的工具非常有用。

Summaries Of Short Text(短文摘要)

对于短文摘要,方法很简单,实际上,除了简单的提示和说明之外,你不需要做任何花哨的事情

from langchain_openai import ChatOpenAI
from langchain import PromptTemplate

llm = ChatOpenAI(temperature=0)

# 创建模板
template = """
%INSTRUCTIONS:
Please summarize the following piece of text.
Respond in a manner that a 5 year old would understand.

%TEXT:
{text}
"""

# 创建一个 LangChain 提示模板,稍后我们可以在其中插入值
prompt = PromptTemplate(
    input_variables=["text"],
    template=template,
)

让我们在网上找一段令人困惑的文字。来源

confusing_text = """
For the next 130 years, debate raged.
Some scientists called Prototaxites a lichen, others a fungus, and still others clung to the notion that it was some kind of tree.
“The problem is that when you look up close at the anatomy, it’s evocative of a lot of different things, but it’s diagnostic of nothing,” says Boyce, an associate professor in geophysical sciences and the Committee on Evolutionary Biology.
“And it’s so damn big that when whenever someone says it’s something, everyone else’s hackles get up: ‘How could you have a lichen 20 feet tall?’”
"""

让我们看看 LLM 会被发送什么提示

print ("------- Prompt Begin -------")

final_prompt = prompt.format(text=confusing_text)
print(final_prompt)

print ("------- Prompt End -------")
------- Prompt Begin -------

%INSTRUCTIONS:
Please summarize the following piece of text.
Respond in a manner that a 5 year old would understand.

%TEXT:

For the next 130 years, debate raged.
Some scientists called Prototaxites a lichen, others a fungus, and still others clung to the notion that it was some kind of tree.
“The problem is that when you look up close at the anatomy, it’s evocative of a lot of different things, but it’s diagnostic of nothing,” says Boyce, an associate professor in geophysical sciences and the Committee on Evolutionary Biology.
“And it’s so damn big that when whenever someone says it’s something, everyone else’s hackles get up: ‘How could you have a lichen 20 feet tall?’”


------- Prompt End -------

最后让我们经过LLM

output = llm.invoke(final_prompt)
print (output)
content="For a long time, scientists argued about what Prototaxites was. Some thought it was a lichen, some thought it was a fungus, and others thought it was a tree. The problem was that when they looked closely at it, it looked like different things but didn't really match anything exactly. It was also really big, so people couldn't agree on what it was." response_metadata={'token_usage': {'completion_tokens': 78, 'prompt_tokens': 166, 'total_tokens': 244}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-6bc63f9a-347b-48b7-9ded-0dc2bff6c71b-0' usage_metadata={'input_tokens': 166, 'output_tokens': 78, 'total_tokens': 244}

这种方法效果很好,但对于较长的文本,管理起来会很麻烦,而且会遇到标记限制。幸运的是,LangChain 开箱即用地支持通过其 load_summarize_chain 进行汇总的不同方法。

Summaries Of Longer Text(长文摘要)

注意:此方法也适用于短文本

from langchain_openai import ChatOpenAI
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter

llm = ChatOpenAI(temperature=0)

让我们加载一个更长的文档

with open('langchain-tutorials/data/PaulGrahamEssays/good.txt', 'r') as file:
    text = file.read()

# Printing the first 285 characters as a preview
print (text[:285])
April 2008(This essay is derived from a talk at the 2008 Startup School.)About a month after we started Y Combinator we came up with the
phrase that became our motto: Make something people want.  We've
learned a lot since then, but if I were choosing now that's still
the one I'd pick.

然后让我们检查一下这个文档中有多少个标记。get_num_tokens 是一个很好的方法。

num_tokens = llm.get_num_tokens(text)

print (f"There are {num_tokens} tokens in your file")
There are 3926 tokens in your file

虽然您可能可以将这段文本塞入提示中,但让我们假设它太大,需要另一种方法。

首先,我们需要将其拆分。这个过程称为“分块”或“拆分”文本为较小的部分。我喜欢 RecursiveCharacterTextSplitter,因为它很容易控制,但您可以尝试很多方法

text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n", "\n"], chunk_size=5000, chunk_overlap=350)
docs = text_splitter.create_documents([text])

print (f"You now have {len(docs)} docs intead of 1 piece of text")
You now have 4 docs intead of 1 piece of text

接下来,我们需要加载一个链,它将为我们连续调用 LLM。

注意:您也可以发挥想象力,让 map_reduce 的前 4 次调用也并行运行

# 准备好使用你的链
chain = load_summarize_chain(llm=llm, chain_type='map_reduce') # verbose=True 可选,用于查看发送到 LLM 的内容
# 使用它。这将遍历 4 个文档,总结块,然后获取摘要的摘要。
output = chain.invoke(docs)
print (output)
{'input_documents': [Document(page_content="April 2008(This essay is derived from a talk at the 2008 Startup School.)About a month after we started Y Combinator we came up with the\nphrase that became our motto: Make something people want.  We've\nlearned a lot since then, but if I were choosing now that's still\nthe one I'd pick.Another thing we tell founders is not to worry too much about the\nbusiness model, at least at first.  Not because making money is\nunimportant, but because it's so much easier than building something\ngreat.A couple weeks ago I realized that if you put those two ideas\ntogether, you get something surprising.  Make something people want.\nDon't worry too much about making money.  What you've got is a\ndescription of a charity.When you get an unexpected result like this, it could either be a\nbug or a new discovery.  Either businesses aren't supposed to be\nlike charities, and we've proven by reductio ad absurdum that one\nor both of the principles we began with is false.  Or we have a new\nidea.I suspect it's the latter, because as soon as this thought occurred\nto me, a whole bunch of other things fell into place.ExamplesFor example, Craigslist.  It's not a charity, but they run it like\none.  And they're astoundingly successful.  When you scan down the\nlist of most popular web sites, the number of employees at Craigslist\nlooks like a misprint. Their revenues aren't as high as they could\nbe, but most startups would be happy to trade places with them.In Patrick O'Brian's novels, his captains always try to get upwind\nof their opponents.  If you're upwind, you decide when and if to\nengage the other ship.  Craigslist is effectively upwind of enormous\nrevenues.  They'd face some challenges if they wanted to make more,\nbut not the sort you face when you're tacking upwind, trying to\nforce a crappy product on ambivalent users by spending ten times\nas much on sales as on development.  [1]I'm not saying startups should aim to end up like Craigslist.\nThey're a product of unusual circumstances.  But they're a good\nmodel for the early phases.Google looked a lot like a charity in the beginning. They didn't\nhave ads for over a year.  At year 1, Google was indistinguishable\nfrom a nonprofit.  If a nonprofit or government organization had\nstarted a project to index the web, Google at year 1 is the limit\nof what they'd have produced.Back when I was working on spam filters I thought it would be a\ngood idea to have a web-based email service with good spam filtering.\nI wasn't thinking of it as a company.  I just wanted to keep people\nfrom getting spammed.  But as I thought more about this project, I\nrealized it would probably have to be a company.  It would cost\nsomething to run, and it would be a pain to fund with grants and\ndonations.That was a surprising realization.  Companies often claim to be\nbenevolent, but it was surprising to realize there were purely\nbenevolent projects that had to be embodied as companies to work.I didn't want to start another company, so I didn't do it.  But if\nsomeone had, they'd probably be quite rich now.  There was a window\nof about two years when spam was increasing rapidly but all the big\nemail services had terrible filters.  If someone had launched a\nnew, spam-free mail service, users would have flocked to it.Notice the pattern here?  From either direction we get to the same\nspot.  If you start from successful startups, you find they often\nbehaved like nonprofits.  And if you start from ideas for nonprofits,\nyou find they'd often make good startups.PowerHow wide is this territory?  Would all good nonprofits be good\ncompanies?  Possibly not.  What makes Google so valuable is that\ntheir users have money.  If you make people with money love you,\nyou can probably get some of it.  But could you also base a successful\nstartup on behaving like a nonprofit to people who don't have money?\nCould you, for example, grow a successful startup out of curing an\nunfashionable but deadly disease like malaria?I'm not sure, but I suspect that if you pushed this idea, you'd be\nsurprised how far it would go.  For example, people who apply to Y\nCombinator don't generally have much money, and yet we can profit\nby helping them, because with our help they could make money.  Maybe\nthe situation is similar with malaria.  Maybe an organization that\nhelped lift its weight off a country could benefit from the resulting\ngrowth.I'm not proposing this is a serious idea.  I don't know anything\nabout malaria.  But I've been kicking ideas around long enough to\nknow when I come across a powerful one.One way to guess how far an idea extends is to ask yourself at what\npoint you'd bet against it.  The thought of betting against benevolence\nis alarming in the same way as saying that something is technically\nimpossible.  You're just asking to be made a fool of, because these\nare such powerful forces.  [2]For example, initially I thought maybe this principle only applied\nto Internet startups.  Obviously it worked for Google, but what"), Document(page_content='is alarming in the same way as saying that something is technically\nimpossible.  You\'re just asking to be made a fool of, because these\nare such powerful forces.  [2]For example, initially I thought maybe this principle only applied\nto Internet startups.  Obviously it worked for Google, but what\nabout Microsoft?  Surely Microsoft isn\'t benevolent?  But when I\nthink back to the beginning, they were.  Compared to IBM they were\nlike Robin Hood.  When IBM introduced the PC, they thought they\nwere going to make money selling hardware at high prices.  But by\ngaining control of the PC standard, Microsoft opened up the market\nto any manufacturer.  Hardware prices plummeted, and lots of people\ngot to have computers who couldn\'t otherwise have afforded them.\nIt\'s the sort of thing you\'d expect Google to do.Microsoft isn\'t so benevolent now.  Now when one thinks of what\nMicrosoft does to users, all the verbs that come to mind begin with\nF.  [3] And yet it doesn\'t seem to pay.\nTheir stock price has been flat for years.  Back when they were\nRobin Hood, their stock price rose like Google\'s.  Could there be\na connection?You can see how there would be.  When you\'re small, you can\'t bully\ncustomers, so you have to charm them.  Whereas when you\'re big you\ncan maltreat them at will, and you tend to, because it\'s easier\nthan satisfying them.  You grow big by being nice, but you can stay\nbig by being mean.You get away with it till the underlying conditions change, and\nthen all your victims escape.  So "Don\'t be evil" may be the most\nvaluable thing Paul Buchheit made for Google, because it may turn\nout to be an elixir of corporate youth.  I\'m sure they find it\nconstraining, but think how valuable it will be if it saves them\nfrom lapsing into the fatal laziness that afflicted Microsoft and\nIBM.The curious thing is, this elixir is freely available to any other\ncompany.  Anyone can adopt "Don\'t be evil."  The catch is that\npeople will hold you to it.  So I don\'t think you\'re going to see\nrecord labels or tobacco companies using this discovery.MoraleThere\'s a lot of external evidence that benevolence works.  But how\ndoes it work?  One advantage of investing in a large number of\nstartups is that you get a lot of data about how they work.  From\nwhat we\'ve seen, being good seems to help startups in three ways:\nit improves their morale, it makes other people want to help them,\nand above all, it helps them be decisive.Morale is tremendously important to a startup鈥攕o important\nthat morale alone is almost enough to determine success.  Startups\nare often described as emotional roller-coasters. One minute you\'re\ngoing to take over the world, and the next you\'re doomed.  The\nproblem with feeling you\'re doomed is not just that it makes you\nunhappy, but that it makes you stop working.  So the downhills\nof the roller-coaster are more of a self fulfilling prophecy than\nthe uphills.  If feeling you\'re going to succeed makes you work\nharder, that probably improves your chances of succeeding, but if\nfeeling you\'re going to fail makes you stop working, that practically\nguarantees you\'ll fail.Here\'s where benevolence comes in.  If you feel you\'re really helping\npeople, you\'ll keep working even when it seems like your startup\nis doomed.  Most of us have some amount of natural benevolence.\nThe mere fact that someone needs you makes you want to help them.\nSo if you start the kind of startup where users come back each day,\nyou\'ve basically built yourself a giant tamagotchi.  You\'ve made\nsomething you need to take care of.Blogger is a famous example of a startup that went through really\nlow lows and survived.  At one point they ran out of money and\neveryone left. Evan Williams came in to work the next day, and there\nwas no one but him.  What kept him going?  Partly that users needed\nhim.  He was hosting thousands of people\'s blogs. He couldn\'t just\nlet the site die.There are many advantages of launching quickly, but the most important\nmay be that once you have users, the tamagotchi effect kicks in.\nOnce you have users to take care of, you\'re forced to figure out\nwhat will make them happy, and that\'s actually very valuable\ninformation.The added confidence that comes from trying to help people can\nalso help you with investors. One of the founders of \nChatterous told \nme recently that he and his cofounder had decided that this service\nwas something the world needed, so they were going to keep working\non it no matter what, even if they had to move back to Canada and live\nin their parents\' basements.Once they realized this, they stopped caring so much what investors thought\nabout them.  They still met with them, but they weren\'t going to\ndie if they didn\'t get their money.  And you know what?  The investors\ngot a lot more interested.  They could sense that the Chatterouses\nwere going to do this startup with or without them.If you\'re really committed and your startup is cheap to run, you\nbecome very hard to kill.  And practically all startups, even the'), Document(page_content='die if they didn\'t get their money.  And you know what?  The investors\ngot a lot more interested.  They could sense that the Chatterouses\nwere going to do this startup with or without them.If you\'re really committed and your startup is cheap to run, you\nbecome very hard to kill.  And practically all startups, even the\nmost successful, come close to death at some point.  So if doing\ngood for people gives you a sense of mission that makes you harder\nto kill, that alone more than compensates for whatever you lose by\nnot choosing a more selfish project.HelpAnother advantage of being good is that it makes other people want\nto help you.  This too seems to be an inborn trait in humans.One of the startups we\'ve funded, Octopart, is currently locked in\na classic battle of good versus evil.  They\'re a search site for\nindustrial components.  A lot of people need to search for components,\nand before Octopart there was no good way to do it.  That, it turned\nout, was no coincidence.Octopart built the right way to search for components.  Users like\nit and they\'ve been growing rapidly.  And yet for most of Octopart\'s\nlife, the biggest distributor, Digi-Key, has been trying to force\nthem take their prices off the site.  Octopart is sending them\ncustomers for free, and yet Digi-Key is trying to make that traffic\nstop.  Why?  Because their current business model depends on\novercharging people who have incomplete information about prices.\nThey don\'t want search to work.The Octoparts are the nicest guys in the world.  They dropped out\nof the PhD program in physics at Berkeley to do this.  They just\nwanted to fix a problem they encountered in their research.  Imagine\nhow much time you could save the world\'s engineers if they could\ndo searches online.  So when I hear that a big, evil company is\ntrying to stop them in order to keep search broken, it makes me\nreally want to help them. It makes me spend more time on the Octoparts\nthan I do with most of the other startups we\'ve funded.  It just\nmade me spend several minutes telling you how great they are.  Why?\nBecause they\'re good guys and they\'re trying to help the world.If you\'re benevolent, people will rally around you: investors,\ncustomers, other companies, and potential employees.  In the long\nterm the most important may be the potential employees.  I think\neveryone knows now that \ngood hackers are much better than mediocre\nones.  If you can attract the best hackers to work for you, as\nGoogle has, you have a big advantage.  And the very best hackers\ntend to be idealistic.  They\'re not desperate for a job.  They can\nwork wherever they want.  So most want to work on things that will\nmake the world better.CompassBut the most important advantage of being good is that it acts as\na compass.  One of the hardest parts of doing a startup is that you\nhave so many choices.  There are just two or three of you, and a\nthousand things you could do. How do you decide?Here\'s the answer: Do whatever\'s best for your users.  You can hold\nonto this like a rope in a hurricane, and it will save you if\nanything can.  Follow it and it will take you through everything\nyou need to do.It\'s even the answer to questions that seem unrelated, like how to\nconvince investors to give you money.  If you\'re a good salesman,\nyou could try to just talk them into it.  But the more reliable\nroute is to convince them through your users: if you make something\nusers love enough to tell their friends, you grow exponentially,\nand that will convince any investor.Being good is a particularly useful strategy for making decisions\nin complex situations because it\'s stateless.  It\'s like telling\nthe truth.  The trouble with lying is that you have to remember\neverything you\'ve said in the past to make sure you don\'t contradict\nyourself.  If you tell the truth you don\'t have to remember anything,\nand that\'s a really useful property in domains where things happen\nfast.For example, Y Combinator has now invested in 80 startups, 57 of\nwhich are still alive.  (The rest have died or merged or been\nacquired.)  When you\'re trying to advise 57 startups, it turns out\nyou have to have a stateless algorithm.  You can\'t have ulterior\nmotives when you have 57 things going on at once, because you can\'t\nremember them.  So our rule is just to do whatever\'s best for the\nfounders.  Not because we\'re particularly benevolent, but because\nit\'s the only algorithm that works on that scale.When you write something telling people to be good, you seem to be\nclaiming to be good yourself.  So I want to say explicitly that I\nam not a particularly good person.  When I was a kid I was firmly\nin the camp of bad.  The way adults used the word good, it seemed\nto be synonymous with quiet, so I grew up very suspicious of it.You know how there are some people whose names come up in conversation\nand everyone says "He\'s such a great guy?"  People never say\nthat about me.  The best I get is "he means well."  I am not claiming'), Document(page_content='in the camp of bad.  The way adults used the word good, it seemed\nto be synonymous with quiet, so I grew up very suspicious of it.You know how there are some people whose names come up in conversation\nand everyone says "He\'s such a great guy?"  People never say\nthat about me.  The best I get is "he means well."  I am not claiming\nto be good.  At best I speak good as a second language.So I\'m not suggesting you be good in the usual sanctimonious way.\nI\'m suggesting it because it works.  It will work not just as a\nstatement of "values," but as a guide to strategy,\nand even a design spec for software.  Don\'t just not be evil.  Be\ngood.Notes[1] Fifty years ago\nit would have seemed shocking for a public company not to pay\ndividends.  Now many tech companies don\'t.  The markets seem to\nhave figured out how to value potential dividends.  Maybe that isn\'t\nthe last step in this evolution.  Maybe markets will eventually get\ncomfortable with potential earnings. (VCs already are, and at least\nsome of them consistently make money.)I realize this sounds like the stuff one used to hear about the\n"new economy" during the Bubble.  Believe me, I was not drinking\nthat kool-aid at the time.  But I\'m convinced there were some \ngood\nideas buried in Bubble thinking.  For example, it\'s ok to focus on\ngrowth instead of profits鈥攂ut only if the growth is genuine.\nYou can\'t be buying users; that\'s a pyramid scheme.   But a company\nwith rapid, genuine growth is valuable, and eventually markets learn\nhow to value valuable things.[2] The idea of starting\na company with benevolent aims is currently undervalued, because\nthe kind of people who currently make that their explicit goal don\'t\nusually do a very good job.It\'s one of the standard career paths of trustafarians to start\nsome vaguely benevolent business.  The problem with most of them\nis that they either have a bogus political agenda or are feebly\nexecuted.  The trustafarians\' ancestors didn\'t get rich by preserving\ntheir traditional culture; maybe people in Bolivia don\'t want to\neither.  And starting an organic farm, though it\'s at least\nstraightforwardly benevolent, doesn\'t help people on the scale that\nGoogle does.Most explicitly benevolent projects don\'t hold themselves sufficiently\naccountable.  They act as if having good intentions were enough to\nguarantee good effects.[3] Users dislike their\nnew operating system so much that they\'re starting petitions to\nsave the old one.  And the old one was nothing special.  The hackers\nwithin Microsoft must know in their hearts that if the company\nreally cared about users they\'d just advise them to switch to OSX.Thanks to Trevor Blackwell, Paul Buchheit, Jessica Livingston,\nand Robert Morris for reading drafts of this.')], 'output_text': 'The essay emphasizes the importance of creating something people want and prioritizing benevolence in startups, using examples like Google and Craigslist. It discusses how being good can attract support from investors and customers, drive innovation, and lead to long-term success. The author highlights the need for genuine growth, accountability, and a focus on user satisfaction in running a startup with benevolent aims.'}

Question & Answering Using Documents As Context(使用文档作为上下文进行问答)

LangChain 问答文档

为了使用 LLM 进行问答,我们必须:

1.传递 LLM 回答问题所需的相关上下文
2.传递我们想要回答的问题

简化后,此过程如下所示“llm(您的上下文 + 您的问题)= 您的答案”

  • 深入探究 - 质疑一本书、向您的自定义文件提问、聊天您的数据 JS(1000 页财务报告)、LangChain 问答网络研讨会(有需求就查看原文章的链接)
  • 示例 - ChatPDF
  • 用例 - 聊天您的文档、向学术论文提问、创建学习指南、参考医疗信息

Simple Q&A Example(简单问答示例)

这里我们来回顾一下 llm 的惯例(你的背景 + 你的问题)= 你的答案

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(temperature=0)
context = """
Rachel is 30 years old
Bob is 45 years old
Kevin is 65 years old
"""

question = "Who is under 40 years old?"

然后将它们合并起来。

output = llm(context + question)

print (output.content.strip())
Rachel is under 40 years old.

随着我们不断提高复杂程度,我们将更多地利用这一惯例。

困难的部分在于,你需要选择将哪些数据放入你的上下文中。这个研究领域被称为“文档检索”,与人工智能记忆紧密相关。

Using Embeddings(使用嵌入)

我非正式地将即将经历的事情称为“VectorStore Dance”。这是拆分文本、嵌入块、将嵌入放入数据库,然后查询它们的过程。有关此内容的完整视频,请查看如何质疑一本书

目标是选择长文本的相关块,但是我们要提取哪些块?最流行的方法是通过比较向量嵌入来提取相似的文本。

from langchain_openai import ChatOpenAI

# 我们将使用的 vectorstore
from langchain.vectorstores import FAISS

# 我们将使用 LangChain 组件来获取文档
from langchain.chains import RetrievalQA

# 简单的文本文档加载器
from langchain.document_loaders import TextLoader

# 嵌入引擎将把我们的文本转换为向量
from langchain_openai import OpenAIEmbeddings

llm = ChatOpenAI(temperature=0)

让我们加载一个更长的文档

loader = TextLoader('langchain-tutorials/data/PaulGrahamEssays/worked.txt')
doc = loader.load()
print (f"You have {len(doc)} document")
print (f"You have {len(doc[0].page_content)} characters in that document")
You have 1 document
You have 74663 characters in that document

现在让我们把长文档分成几个小部分

text_splitter = RecursiveCharacterTextSplitter(chunk_size=3000, chunk_overlap=400)
docs = text_splitter.split_documents(doc)
# 获取字符总数,以便我们稍后查看平均值
num_total_characters = sum([len(x.page_content) for x in docs])

print (f"Now you have {len(docs)} documents that have an average of {num_total_characters / len(docs):,.0f} characters (smaller pieces)")
Now you have 29 documents that have an average of 2,930 characters (smaller pieces)
# 准备好你的嵌入引擎
embeddings = OpenAIEmbeddings()

# 嵌入您的文档并与伪数据库中的原始文本相结合。注意:这将对 OpenAI 进行 API 调用
docsearch = FAISS.from_documents(docs, embeddings)

创建您的检索引擎

qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=docsearch.as_retriever())

现在该问问题了。检索器将获取类似的文档,并结合您的问题,以供 LLM 进行推理。

注意:这看起来可能不多,但这里的神奇之处在于我们不必传递完整的原始文档。

query = "What does the author describe as good work?"
qa.run(query)
"The author describes good work as something that may not be prestigious at the moment but is genuinely interesting to the individual. They emphasize the importance of being drawn to work despite its lack of current prestige, as it can lead to real discoveries and indicate the right motives. The author suggests that working on things that aren't prestigious doesn't guarantee being on the right track, but it at least ensures not being on the most common type of wrong one."

如果你想做更多,你可以将其连接到云矢量数据库,使用像 metal 这样的工具,并开始使用外部数据源管理你的文档

Extraction(提取)

提取是从一段文本中解析数据的过程。这通常与输出解析一起使用,以便构造我们的数据。

  • 深入研究 - 使用 LLM 从文本中提取数据(专家级文本提取、OpenAI 的结构化输出(清理脏数据)
  • 示例 - OpeningAttributes
  • 用例:从句子中提取结构化行以插入数据库,从长文档中提取多行以插入数据库,从用户查询中提取参数以进行 API 调用
    一个流行的提取库是 Kor。我们今天不会介绍它,但我强烈建议您查看它以进行高级提取。
# 帮助构建我们的聊天信息
from langchain.schema import HumanMessage
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate

# 我们将使用聊天模型,默认为 gpt-3.5-turbo
from langchain_openai import ChatOpenAI

# 解析输出并获取结构化数据
from langchain.output_parsers import StructuredOutputParser, ResponseSchema

chat_model = ChatOpenAI(temperature=0, model_name='gpt-3.5-turbo')

Vanilla Extraction

让我们从一个简单的例子开始。在这里,我只需提供一个带有我想要的输出类型的指令提示。

instructions = """
You will be given a sentence with fruit names, extract those fruit names and assign an emoji to them
Return the fruit name and emojis in a python dictionary
"""

fruit_names = """
Apple, Pear, this is an kiwi
"""
# 制作将说明与水果名称结合起来的提示
prompt = (instructions + fruit_names)

# Call the LLM
output = chat_model([HumanMessage(content=prompt)])

print (output.content)
print (type(output.content))
{
    "Apple": "🍎",
    "Pear": "🍐",
    "kiwi": "🥝"
}
<class 'str'>

让我们把它变成一个合适的 Python 字典

output_dict = eval(output.content)

print (output_dict)
print (type(output_dict))
{'Apple': '🍎', 'Pear': '🍐', 'kiwi': '🥝'}
<class 'dict'>

虽然这次有效,但对于更高级的用例来说,这不是一个长期可靠的方法

Using LangChain’s Response Schema(使用 LangChain 的响应模式)

LangChain 的响应模式将为我们做两件事:

1.使用真实格式说明自动生成提示。这很棒,因为我不需要担心提示工程方面,我会把这留给 LangChain!

2.读取 LLM 的输出并将其转换为适合我的 Python 对象

在这里我定义了我想要的模式。我将从伪聊天消息中提取用户想要播放的歌曲和艺术家。

# 我想要的模式
response_schemas = [
ResponseSchema(name="artist", description="音乐艺术家的名字"),
ResponseSchema(name="song", description="艺术家演奏的歌曲的名字")
]

# 解析器将在我的模式中查找 LLM 输出并将其返回给我
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
# LangChain 制作的格式指令。我们来看看
format_instructions = output_parser.get_format_instructions()
print(format_instructions)
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
	"artist": string  // 音乐艺术家的名字
	"song": string  // 艺术家演奏的歌曲的名字
}
```
# 将所有内容整合在一起的提示模板
# 注意:这是一个与之前不同的提示模板,因为我们使用的是聊天模型

prompt = ChatPromptTemplate(
messages=[
HumanMessagePromptTemplate.from_template("Given a command from the user, extract the artist and song names \n \
                                                    {format_instructions}\n{user_prompt}")
],
input_variables=["user_prompt"],
partial_variables={"format_instructions": format_instructions}
)
fruit_query = prompt.format_prompt(user_prompt="I really like So Young by Portugal. The Man")
print (fruit_query.messages[0].content)
Given a command from the user, extract the artist and song names 
                                                     The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
	"artist": string  // 音乐艺术家的名字
	"song": string  // 艺术家演奏的歌曲的名字
}
```
I really like So Young by Portugal. The Man
fruit_output = chat_model(fruit_query.to_messages())
output = output_parser.parse(fruit_output.content)

print (output)
print (type(output))
{'artist': 'Portugal. The Man', 'song': 'So Young'}
<class 'dict'>

太棒了,现在我们有了一个以后可以使用的字典

警告:解析器会查找特定格式的 LLM 输出。您的模型可能不会每次都输出相同的格式。请确保处理此错误。GPT4 和未来的迭代将更加可靠。

如需更高级的解析,请查看 Kor

Evaluation(评估)

评估是对应用程序输出进行质量检查的过程。我们可以运行正常的、确定性的代码测试,但由于自然语言的不可预测性和多变性,判断 LLM 的输出更加困难。LangChain 提供了可帮助我们完成这一过程的工具。

  • 深入探究 - 即将推出
  • 示例 - Lance Martin 的高级自动评估器
  • 用例:对摘要或问答管道进行质量检查,检查摘要管道的输出
# 嵌入、存储和检索
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA

# 模型和文档加载器
from langchain_openai import ChatOpenAI
from langchain.document_loaders import TextLoader

# 评估
from langchain.evaluation.qa import QAEvalChain

llm = ChatOpenAI(temperature=0)
# 之前的长论文
loader = TextLoader('langchain-tutorials/data/PaulGrahamEssays/worked.txt')
doc = loader.load()

print (f"You have {len(doc)} document")
print (f"You have {len(doc[0].page_content)} characters in that document")
You have 1 document
You have 74663 characters in that document

首先让我们进行 Vectorestore dance,这样我们就可以进行问答

text_splitter = RecursiveCharacterTextSplitter(chunk_size=3000, chunk_overlap=400)
docs = text_splitter.split_documents(doc)

# 获取字符总数,以便我们稍后查看平均值
num_total_characters = sum([len(x.page_content) for x in docs])

print (f"Now you have {len(docs)} documents that have an average of {num_total_characters / len(docs):,.0f} characters (smaller pieces)")
Now you have 29 documents that have an average of 2,930 characters (smaller pieces)
# 嵌入和文档存储
embeddings = OpenAIEmbeddings()
docsearch = FAISS.from_documents(docs, embeddings)

制作您的检索链。请注意,我现在有一个 input_key 参数。这会告诉链,我提供的字典中的哪个键包含我的提示/查询。我指定问题以匹配下面字典中的问题

chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=docsearch.as_retriever(), input_key="question")

现在,我将把一系列问题和基本事实答案传递给我知道是正确的 LLM(我以人类的身份验证了它们)。

question_answers = [
    {'question' : "Which company sold the microcomputer kit that his friend built himself?", 'answer' : 'Healthkit'},
    {'question' : "What was the small city he talked about in the city that is the financial capital of USA?", 'answer' : 'Yorkville, NY'}
]

我将使用 chain.apply 分别逐一运行我的两个问题。

其中一个很酷的部分是,我将得到我的问题和答案字典列表,但字典 result 中会有另一个键,它将是 LLM 的输出。

注意:我特意让我的第二个问题模棱两可,难以一次性回答,这样 LLM 就会答错(这里没有答错)

predictions = chain.apply(question_answers)
predictions
D:\wuzhongyanqiu\envs\pytorch\Lib\site-packages\langchain_core\_api\deprecation.py:139: LangChainDeprecationWarning: The method `Chain.apply` was deprecated in langchain 0.1.0 and will be removed in 0.3.0. Use batch instead.
  warn_deprecated(





[{'question': 'Which company sold the microcomputer kit that his friend built himself?',
  'answer': 'Healthkit',
  'result': 'The company that sold the microcomputer kit that his friend built himself was Heathkit.'},
 {'question': 'What was the small city he talked about in the city that is the financial capital of USA?',
  'answer': 'Yorkville, NY',
  'result': "The small city mentioned in the text is Yorkville, which was the author's new home. The financial capital of the USA is New York City."}]

然后,我们让 LLM 将我的标准答案(答案键)与 LLM 的结果(结果键)进行比较。

或者简单地说,我们要求 LLM 自己评分。我们生活在一个多么疯狂的世界里。

# 启动您的评估链
eval_chain = QAEvalChain.from_llm(llm)

# 让它自己评分。下面的代码帮助 eval_chain 知道不同部分的位置
graded_outputs = eval_chain.evaluate(
question_answers,
predictions,
question_key="question",
prediction_key="result",
answer_key='answer')
graded_outputs
[{'results': 'CORRECT'}, {'results': 'CORRECT'}]

这是正确的!请注意问题 1 中的答案是“Healthkit”,而预测是“微型计算机套件由 Heathkit 出售”。LLM 知道答案和结果相同,并给了我们一个“正确”的标签。太棒了。

对于问题 2,它知道它们不一样,并给了我们一个“不正确”的标签。(这里给了正确的标签,因为答对了)

Querying Tabular Data(查询表格数据)

世界上最常见的数据类型是表格形式(好吧,好吧,除了非结构化数据)。能够使用 LangChain 查询这些数据并将其传递给 LLM 是非常强大的

  • 深入探究 - 即将推出
  • 示例 - 待定
  • 用例:使用 LLM 查询有关用户的数据,进行数据分析,从数据库获取实时信息

如需进一步阅读,请查看“代理 + 表格数据”(Pandas、SQL、CSV)

让我们使用自然语言查询 SQLite 数据库。我们将查看旧金山树木数据集。

from langchain import OpenAI, SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain
llm = OpenAI(temperature=0)

我们首先要指定数据的位置并准备好连接

sqlite_db_path = 'langchain-tutorials/data/San_Francisco_Trees.db'
db = SQLDatabase.from_uri(f"sqlite:///{sqlite_db_path}")

然后我们将创建一个包含 LLM 和 DB 的链。我设置了 verbose=True,这样您就可以看到幕后发生了什么。

db_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)
D:\wuzhongyanqiu\envs\pytorch\Lib\site-packages\langchain_experimental\sql\base.py:77: UserWarning: Directly instantiating an SQLDatabaseChain with an llm is deprecated. Please instantiate with llm_chain argument or using the from_llm class method.
  warnings.warn(
db_chain.run("How many Species of trees are there in San Francisco?")
[1m> Entering new SQLDatabaseChain chain...[0m
How many Species of trees are there in San Francisco?
SQLQuery:[32;1m[1;3mSELECT COUNT(DISTINCT qSpecies) FROM SFTrees[0m
SQLResult: [33;1m[1;3m[(578,)][0m
Answer:[32;1m[1;3mThere are 578 species of trees in San Francisco.[0m
[1m> Finished chain.[0m





'There are 578 species of trees in San Francisco.'

这太棒了!实际上这里有几个步骤。

步骤:

1.查找要使用的表

2.查找要使用的列

3.构建正确的 sql 查询

4.执行该查询

5.获取结果

6.返回自然语言响应

让我们通过 pandas 进行确认

import sqlite3
import pandas as pd

# 连接到 SQLite 数据库
connection = sqlite3.connect(sqlite_db_path)

# 定义你的 SQL 查询
query = "SELECT count(distinct qSpecies) FROM SFTrees"

# 将 SQL 查询读入 Pandas DataFrame
df = pd.read_sql_query(query, connection)

# 关闭连接
connection.close()
# 在第一列第一个单元格显示结果
print(df.iloc[0,0])
578

很好!答案一致。

Code Understanding(代码理解)

LLM 最令人兴奋的能力之一是代码理解。由于人工智能的帮助,世界各地的人们都在提高速度和质量。其中很大一部分是拥有一个可以理解代码并帮助您完成特定任务的 LLM。

  • 深入探究 - 即将推出
  • 示例 - 待定
  • 用例:Co-Pilot 式功能可以帮助回答特定库中的问题,帮助您生成新代码
# 帮助程序读取本地文件
import os

# 矢量支持
from langchain.vectorstores import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings

# 模型和链
from langchain.chat_models import ChatOpenAI

# 文本分割器
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader

llm = ChatOpenAI(model_name='gpt-3.5-turbo')

我们将再次进行Vectorstore dance

embeddings = OpenAIEmbeddings(disallowed_special=())

我把一个小的 Python 包 The Fuzz(个人最喜欢的独立包)放在这个 repo 的数据文件夹中。

下面的循环将遍历库中的每个文件并将其加载为文档

root_dir = 'langchain-tutorials/data/thefuzz'
docs = []

# 浏览每个文件夹
for dirpath, dirnames, filenames in os.walk(root_dir):
    
    # 浏览每个文件
    for file in filenames:
        try: 
            # 将文件加载为文档并拆分
            loader = TextLoader(os.path.join(dirpath, file), encoding='utf-8')
            docs.extend(loader.load_and_split())
        except Exception as e: 
            pass

让我们看一个文档示例。它只是代码!

print (f"You have {len(docs)} documents\n")
print ("------ Start Document ------")
print (docs[0].page_content[:300])
You have 175 documents

------ Start Document ------
# .editorconfig
# http://editorconfig.org/
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.bat]
end_of_line = crlf

[*.go]
indent_size = 4
indent_style = tab

[*.html]
indent_size = 4

[*Makefile]

嵌入并存储在文档库中。这将对 OpenAI 进行 API 调用

docsearch = FAISS.from_documents(docs, embeddings)
# 准备好我们的检索器
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=docsearch.as_retriever())
query = "What function do I use if I want to find the most similar item in a list of items?"
output = qa.run(query)
print (output)
You can use the `extractOne` function from the `process` module in the `thefuzz` library. The `extractOne` function will return the single best match along with its score from a list of choices based on the similarity between the query and the choices.
query = "Can you write the code to use the process.extractOne() function? Only respond with code. No other text or explanation"
output = qa.run(query)
print (output)
```python
best = process.extractOne(query, choices)
```

Interacting with APIs(与 API 交互)

LangChain API 交互文档

如果您需要的数据或操作位于 API 后面,则需要 LLM 与 API 交互

  • 深入探究 - 即将推出
  • 示例 - 待定
  • 用例:了解用户的请求并执行操作,能够自动化更多实际工作流程

此主题与代理和插件密切相关,但我们将在本部分中介绍一个简单的用例。有关更多信息,请查看 LangChain + 插件文档。

from langchain.chains import APIChain
from langchain.llms import OpenAI

llm = OpenAI(temperature=0)

LangChain 的 APIChain 能够读取 API 文档并了解需要调用哪个端点。

在这种情况下,我编写了(故意草率的)API 文档来演示其工作原理

api_docs = """

BASE URL: https://restcountries.com/

API Documentation:

The API endpoint /v3.1/name/{name} Used to find informatin about a country. All URL parameters are listed below:
    - name: Name of country - Ex: italy, france
    
The API endpoint /v3.1/currency/{currency} Uesd to find information about a region. All URL parameters are listed below:
    - currency: 3 letter currency. Example: USD, COP
    
Woo! This is my documentation
"""

chain_new = APIChain.from_llm_and_api_docs(llm, api_docs, verbose=True, limit_to_domains=['https://restcountries.com/v3.1/name/france'])

让我们尝试进行针对国家/地区端点的 API 调用

chain_new.run('Can you tell me information about france?')
[1m> Entering new APIChain chain...[0m
[32;1m[1;3m https://restcountries.com/v3.1/name/france[0m
[33;1m[1;3m[{"name":{"common":"France","official":"French Republic","nativeName":{"fra":{"official":"République française","common":"France"}}},"tld":[".fr"],"cca2":"FR","ccn3":"250","cca3":"FRA","cioc":"FRA","independent":true,"status":"officially-assigned","unMember":true,"currencies":{"EUR":{"name":"Euro","symbol":"€"}},"idd":{"root":"+3","suffixes":["3"]},"capital":["Paris"],"altSpellings":["FR","French Republic","République française"],"region":"Europe","subregion":"Western Europe","languages":{"fra":"French"},"translations":{"ara":{"official":"الجمهورية الفرنسية","common":"فرنسا"},"bre":{"official":"Republik Frañs","common":"Frañs"},"ces":{"official":"Francouzská republika","common":"Francie"},"cym":{"official":"French Republic","common":"France"},"deu":{"official":"Französische Republik","common":"Frankreich"},"est":{"official":"Prantsuse Vabariik","common":"Prantsusmaa"},"fin":{"official":"Ranskan tasavalta","common":"Ranska"},"fra":{"official":"République française","common":"France"},"hrv":{"official":"Francuska Republika","common":"Francuska"},"hun":{"official":"Francia Köztársaság","common":"Franciaország"},"ita":{"official":"Repubblica francese","common":"Francia"},"jpn":{"official":"フランス共和国","common":"フランス"},"kor":{"official":"프랑스 공화국","common":"프랑스"},"nld":{"official":"Franse Republiek","common":"Frankrijk"},"per":{"official":"جمهوری فرانسه","common":"فرانسه"},"pol":{"official":"Republika Francuska","common":"Francja"},"por":{"official":"República Francesa","common":"França"},"rus":{"official":"Французская Республика","common":"Франция"},"slk":{"official":"Francúzska republika","common":"Francúzsko"},"spa":{"official":"República francés","common":"Francia"},"srp":{"official":"Француска Република","common":"Француска"},"swe":{"official":"Republiken Frankrike","common":"Frankrike"},"tur":{"official":"Fransa Cumhuriyeti","common":"Fransa"},"urd":{"official":"جمہوریہ فرانس","common":"فرانس"},"zho":{"official":"法兰西共和国","common":"法国"}},"latlng":[46.0,2.0],"landlocked":false,"borders":["AND","BEL","DEU","ITA","LUX","MCO","ESP","CHE"],"area":551695.0,"demonyms":{"eng":{"f":"French","m":"French"},"fra":{"f":"Française","m":"Français"}},"flag":"\uD83C\uDDEB\uD83C\uDDF7","maps":{"googleMaps":"https://goo.gl/maps/g7QxxSFsWyTPKuzd7","openStreetMaps":"https://www.openstreetmap.org/relation/1403916"},"population":67391582,"gini":{"2018":32.4},"fifa":"FRA","car":{"signs":["F"],"side":"right"},"timezones":["UTC-10:00","UTC-09:30","UTC-09:00","UTC-08:00","UTC-04:00","UTC-03:00","UTC+01:00","UTC+02:00","UTC+03:00","UTC+04:00","UTC+05:00","UTC+10:00","UTC+11:00","UTC+12:00"],"continents":["Europe"],"flags":{"png":"https://flagcdn.com/w320/fr.png","svg":"https://flagcdn.com/fr.svg","alt":"The flag of France is composed of three equal vertical bands of blue, white and red."},"coatOfArms":{"png":"https://mainfacts.com/media/images/coats_of_arms/fr.png","svg":"https://mainfacts.com/media/images/coats_of_arms/fr.svg"},"startOfWeek":"monday","capitalInfo":{"latlng":[48.87,2.33]},"postalCode":{"format":"#####","regex":"^(\\d{5})$"}}][0m

[1m> Finished chain.[0m





' The response from the API provides information about France, including its official name, native name, top-level domain, country codes, currencies, capital, region, languages, translations, borders, area, population, timezones, continents, flags, coat of arms, and postal code format.'

Chatbots(聊天机器人)

LangChain 聊天机器人文档

聊天机器人使用我们已经研究过的许多工具,并增加了一个重要主题:记忆。记忆有很多种类型,您可以自行尝试,看看哪种最适合您。

  • 深入探究 - 即将推出
  • 示例 - ChatBase(关联链接)、NexusGPT、ChatPDF
  • 用例:与用户进行实时交互,为用户提供易于理解的 UI 以提出自然语言问题
from langchain.llms import OpenAI
from langchain import LLMChain
from langchain.prompts.prompt import PromptTemplate

# 聊天特定组件
from langchain.memory import ConversationBufferMemory

对于此用例,我将向您展示如何自定义提供给聊天机器人的上下文。

您可以传递有关机器人应如何响应的指令,以及它所需的任何其他相关信息。

template = """
You are a chatbot that is unhelpful.
Your goal is to not help the user but only make jokes.
Take what the user is saying and make a joke out of it

{chat_history}
Human: {human_input}
Chatbot:"""

prompt = PromptTemplate(
    input_variables=["chat_history", "human_input"], 
    template=template
)
memory = ConversationBufferMemory(memory_key="chat_history")
llm_chain = LLMChain(
    llm=OpenAI(), 
    prompt=prompt, 
    verbose=True, 
    memory=memory
)
llm_chain.predict(human_input="Is an pear a fruit or vegetable?")
[1m> Entering new LLMChain chain...[0m
Prompt after formatting:
[32;1m[1;3m
You are a chatbot that is unhelpful.
Your goal is to not help the user but only make jokes.
Take what the user is saying and make a joke out of it


Human: Is an pear a fruit or vegetable?
Chatbot:[0m

[1m> Finished chain.[0m





" I asked a pear if it was a fruit or vegetable, but it couldn't decide. It was too busy being an a-peeling snack."
llm_chain.predict(human_input="What was one of the fruits I first asked you about?")
[1m> Entering new LLMChain chain...[0m
Prompt after formatting:
[32;1m[1;3m
You are a chatbot that is unhelpful.
Your goal is to not help the user but only make jokes.
Take what the user is saying and make a joke out of it

Human: Is an pear a fruit or vegetable?
AI:  I asked a pear if it was a fruit or vegetable, but it couldn't decide. It was too busy being an a-peeling snack.
Human: What was one of the fruits I first asked you about?
Chatbot:[0m

[1m> Finished chain.[0m





' I believe it was the pear-fectly ambiguous pear.'

注意我的第一次互动是如何被放入第二次互动的提示中的。这是记忆片段在起作用。

有很多种方式来组织对话,请查看文档中的不同方式

Agents(代理)

代理是LLM中最热门的🔥话题之一。代理是决策者,可以查看数据,推理下一步应该做什么,并通过工具为您执行该操作

  • 深入探究 - 代理简介、LangChain 代理网络研讨会,即将推出更深入的探究
  • 示例 - 待定
  • 用例:无需人工输入即可自主运行程序

代理的高级用途示例出现在 BabyAGI 和 AutoGPT 中

# Helpers
import os
import json

from langchain.llms import OpenAI

# Agent imports
from langchain.agents import load_tools
from langchain.agents import initialize_agent

# Tool imports
from langchain.agents import Tool
from langchain.utilities import GoogleSearchAPIWrapper
from langchain.utilities import TextRequestsWrapper

在这个例子中,我将提取谷歌搜索结果。如果您需要一份研究项目的网站列表,您可能需要这样做。

您可以在以下网址注册这两个密钥

GOOGLE_API_KEY GOOGLE_CSE_ID

GOOGLE_CSE_ID = os.getenv('GOOGLE_CSE_ID', '21bd0becc4a7a471e')
GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY', 'YourAPIKeyIfNotSet')
llm = OpenAI(temperature=0)

初始化你将要使用的两个工具。在这个例子中,我们将搜索谷歌,并赋予 LLM 执行 Python 代码的能力

search = GoogleSearchAPIWrapper(google_api_key=GOOGLE_API_KEY, google_cse_id=GOOGLE_CSE_ID)

requests = TextRequestsWrapper()

把两种工具都放在工具包里

toolkit = [
    Tool(
        name = "Search",
        func=search.run,
        description="useful for when you need to search google to answer questions about current events"
    ),
    Tool(
        name = "Requests",
        func=requests.get,
        description="Useful for when you to make a request to a URL"
    ),
]

创建你的代理,为其提供工具、LLM 和代理类型

agent = initialize_agent(toolkit, llm, agent="zero-shot-react-description", verbose=True, return_intermediate_steps=True)

现在问它一个问题,我会给它一个应该去谷歌搜索的问题

response = agent({"input":"What is the capital of canada?"})
response['output']

很好,没错。现在我们来问一个需要列出当前目录的问题

response = agent({"input":"Tell me what the comments are about on this webpage https://news.ycombinator.com/item?id=34425779"})
response['output']

调用api这里agent已经给出了它要做的action,只是连接api那里因为某些原因连接不上,就不做展示了。

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Docker Cookbook, 2nd Edition》是一本关于Docker技术的实用指南,通过实例来展示如何在不同场景下使用Docker来构建、发布和管理应用程序。 该书的第二版内容更新了适用于最新版本Docker的技术和最佳实践,并加入了一些新的示例。书中共包含近百个实际问题和解决方案,从基本到高级的Docker用法都有涉及。 在这本书中,你将学到如何安装和配置Docker,创建自定义镜像,管理容器和网络,以及优化Docker的性能。此外,还有专门章节讲解如何在不同的应用场景中使用Docker,如Web开发、数据库管理、大数据处理、持续集成和部署等。 在阅读过程中,你将遇到一些常见的Docker问题,并找到解决的方法。例如,如何使用Docker Compose来管理复杂的应用组合,如何使用Docker Swarm构建容器集群,如何优化Docker容器的性能等。每个问题都有一个具体的解决方案,方便读者快速实施。 此外,书中还介绍了一些与Docker相关的组件和工具,如Docker Machine、Docker Registry、Docker Data Volumes等。你将了解到这些工具如何辅助你更好地使用Docker,并解决一些常见的问题。 总体而言,《Docker Cookbook, 2nd Edition》是一本非常实用的Docker指南,适合有一定基础的读者阅读。通过这本书,你将能够更加深入地理解和应用Docker技术,提升自己在容器化领域的技能水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值