From 815c47fe262f577a7865946c29e390d5cb1c0c79 Mon Sep 17 00:00:00 2001 From: joyenjoye Date: Sun, 16 Jul 2023 15:29:11 +0800 Subject: [PATCH 1/5] Update Chapter 3 --- .../3.储存 Memory.ipynb | 1697 +++++++++++++++++ .../3.存储 Memory.ipynb | 1 - 2 files changed, 1697 insertions(+), 1 deletion(-) create mode 100644 content/LangChain for LLM Application Development/3.储存 Memory.ipynb delete mode 100644 content/LangChain for LLM Application Development/3.存储 Memory.ipynb diff --git a/content/LangChain for LLM Application Development/3.储存 Memory.ipynb b/content/LangChain for LLM Application Development/3.储存 Memory.ipynb new file mode 100644 index 0000000..06d63e7 --- /dev/null +++ b/content/LangChain for LLM Application Development/3.储存 Memory.ipynb @@ -0,0 +1,1697 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a786c77c", + "metadata": { + "tags": [] + }, + "source": [ + "# 第三章 储存\n", + "\n", + " - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n", + " - [二、对话缓存储存 ](#二、对话缓存储存--)\n", + " - [2.1 开始对话,第一轮](#2.1-开始对话,第一轮)\n", + " - [2.2 第二轮对话](#2.2-第二轮对话)\n", + " - [2.3 第三轮对话](#2.3-第三轮对话)\n", + " - [2.4 .memory.buffer储存了当前为止所有的对话信息](#2.4-.memory.buffer储存了当前为止所有的对话信息)\n", + " - [2.5 也可以通过memory.load_memory_variables({})打印历史消息](#2.5-也可以通过memory.load_memory_variables({})打印历史消息)\n", + " - [2.6 添加指定的输入输出内容到记忆缓存区](#2.6-添加指定的输入输出内容到记忆缓存区)\n", + " - [三、对话缓存窗口储存](#三、对话缓存窗口储存)\n", + " - [3.1 向memory添加两轮对话,并查看记忆变量当前的记录](#3.1-向memory添加两轮对话,并查看记忆变量当前的记录)\n", + " - [3.2 在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆](#3.2-在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆)\n", + " - [3.3 将对话缓存窗口记忆应用到对话链中](#3.3-将对话缓存窗口记忆应用到对话链中)\n", + " - [四、对话token缓存储存](#四、对话token缓存储存)\n", + " - [4.1 导入相关包和API密钥](#4.1-导入相关包和API密钥)\n", + " - [4.2 限制token数量,进行测试](#4.2-限制token数量,进行测试)\n", + " - [4.3 中文例子](#4.3-中文例子)\n", + " - [五、对话摘要缓存储存](#五、对话摘要缓存储存)\n", + " - [5.1 创建一个长字符串,其中包含某人的日程安排](#5.1-创建一个长字符串,其中包含某人的日程安排)\n", + " - [5.2 基于上面的memory,新建一个对话链](#5.2-基于上面的memory,新建一个对话链)\n", + " - [5.3 中文例子](#5.3-中文例子)\n" + ] + }, + { + "cell_type": "markdown", + "id": "7e10db6f", + "metadata": {}, + "source": [ + "当你与那些语言模型进行交互的时候,他们不会记得你之前和他进行的交流内容,这在我们构建一些应用程序(如聊天机器人)的时候,是一个很大的问题 -- 显得不够智能!因此,在本节中我们将介绍 LangChain 中的储存模块,即如何将先前的对话嵌入到语言模型中的,使其具有连续对话的能力。\n", + "\n", + "当使用 LangChain 中的储存(Memory)模块时,它可以帮助保存和管理历史聊天消息,以及构建关于特定实体的知识。这些组件可以跨多轮对话储存信息,并允许在对话期间跟踪特定信息和上下文。\n", + "\n", + "LangChain 提供了多种储存类型。其中,缓冲区储存允许保留最近的聊天消息,摘要储存则提供了对整个对话的摘要。实体储存 则允许在多轮对话中保留有关特定实体的信息。这些记忆组件都是模块化的,可与其他组件组合使用,从而增强机器人的对话管理能力。储存模块可以通过简单的API调用来访问和更新,允许开发人员更轻松地实现对话历史记录的管理和维护。\n", + "\n", + "此次课程主要介绍其中四种储存模块,其他模块可查看文档学习。\n", + "- 对话缓存储存 (ConversationBufferMemory)\n", + "- 对话缓存窗口储存 (ConversationBufferWindowMemory)\n", + "- 对话令牌缓存储存 (ConversationTokenBufferMemory)\n", + "- 对话摘要缓存储存 (ConversationSummaryBufferMemory)\n", + "\n", + "在LangChain中,储存 指的是大语言模型(LLM)的短期记忆。为什么是短期记忆?那是因为LLM训练好之后 (获得了一些长期记忆),它的参数便不会因为用户的输入而发生改变。当用户与训练好的LLM进行对话时,LLM会暂时记住用户的输入和它已经生成的输出,以便预测之后的输出,而模型输出完毕后,它便会“遗忘”之前用户的输入和它的输出。因此,之前的这些信息只能称作为LLM的短期记忆。 \n", + " \n", + "为了延长LLM短期记忆的保留时间,则需要借助一些外部储存方式来进行记忆,以便在用户与LLM对话中,LLM能够尽可能的知道用户与它所进行的历史对话信息。 " + ] + }, + { + "cell_type": "markdown", + "id": "1ca56e6b-1e07-4405-a1ca-f4237f20fa75", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## 一、设置OpenAI API Key\n", + "\n", + "登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n", + "\n", + "- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n", + "- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n", + "\n", + "

\n", + " OPENAI_API_KEY=\"your_api_key\" \n", + "

\n", + " \n", + " 替换\"your_api_key\"为你自己的 API Key" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6932bd47-c6d5-4794-8102-a12b84412a93", + "metadata": {}, + "outputs": [], + "source": [ + "# 下载需要的包python-dotenv和openai\n", + "# 如果你需要查看安装过程日志,可删除 -q\n", + "!pip install -q python-dotenv\n", + "!pip install -q openai" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "10446712-9fa6-4d71-94ce-2ea4cf197e54", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import openai\n", + "from dotenv import find_dotenv, load_dotenv\n", + "\n", + "# 读取本地/项目的环境变量。\n", + "\n", + "# find_dotenv()寻找并定位.env文件的路径\n", + "# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中\n", + "# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n", + "_ = load_dotenv(find_dotenv())\n", + "\n", + "# 获取环境变量 OPENAI_API_KEY\n", + "openai.api_key = os.environ[\"OPENAI_API_KEY\"]" + ] + }, + { + "cell_type": "markdown", + "id": "1297dcd5", + "metadata": { + "tags": [] + }, + "source": [ + "## 二、对话缓存储存\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "ffa8cd26-45c5-4bae-90b2-b07d23bf3bb2", + "metadata": {}, + "source": [ + "### 2.1 英文版" + ] + }, + { + "cell_type": "markdown", + "id": "b7e77a3d-7aaa-48c1-b219-19bd6f4eb674", + "metadata": { + "tags": [] + }, + "source": [ + "#### 2.1.1 初始化对话模型" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "20ad6fe2", + "metadata": { + "height": 98 + }, + "outputs": [], + "source": [ + "from langchain.chains import ConversationChain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.memory import ConversationBufferMemory" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "88bdf13d", + "metadata": { + "height": 133 + }, + "outputs": [], + "source": [ + "# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。\n", + "# 如果你想要每次得到不一样的有新意的答案,可以尝试增大该参数。\n", + "llm = ChatOpenAI(temperature=0.0) \n", + "\n", + "memory = ConversationBufferMemory()\n", + "\n", + "# 新建一个 ConversationChain Class 实例\n", + "# verbose参数设置为True时,程序会输出更详细的信息,以提供更多的调试或运行时信息。\n", + "# 相反,当将verbose参数设置为False时,程序会以更简洁的方式运行,只输出关键的信息。\n", + "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )" + ] + }, + { + "cell_type": "markdown", + "id": "dea83837", + "metadata": { + "tags": [] + }, + "source": [ + "#### 2.1.2 第一轮对话" + ] + }, + { + "cell_type": "markdown", + "id": "1a3b4c42", + "metadata": {}, + "source": [ + "当我们运行预测(predict)时,生成了一些提示,如下所见,他说“以下是人类和AI之间友好的对话,AI健谈“等等,这实际上是LangChain生成的提示,以使系统进行希望和友好的对话,并且必须保存对话,并提示了当前已完成的模型链。" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "db24677d", + "metadata": { + "height": 47 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "\n", + "Human: Hi, my name is Andrew\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "\"Hello Andrew! It's nice to meet you. How can I assist you today?\"" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"Hi, my name is Andrew\")" + ] + }, + { + "cell_type": "markdown", + "id": "e71564ad", + "metadata": {}, + "source": [ + "#### 2.1.3 第二轮对话" + ] + }, + { + "cell_type": "markdown", + "id": "54d006bd", + "metadata": {}, + "source": [ + "当我们进行第二轮对话时,它会保留上面的提示" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "cc3ef937", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "Human: Hi, my name is Andrew\n", + "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", + "Human: What is 1+1?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'1+1 is equal to 2.'" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"What is 1+1?\")" + ] + }, + { + "cell_type": "markdown", + "id": "33cb734b", + "metadata": {}, + "source": [ + "#### 2.1.4 第三轮对话" + ] + }, + { + "cell_type": "markdown", + "id": "0393df3d", + "metadata": {}, + "source": [ + "为了验证他是否记忆了前面的对话内容,我们让他回答前面已经说过的内容(我的名字),可以看到他确实输出了正确的名字,因此这个对话链随着往下进行会越来越长" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "acf3339a", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "Human: Hi, my name is Andrew\n", + "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", + "Human: What is 1+1?\n", + "AI: 1+1 is equal to 2.\n", + "Human: What is my name?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Your name is Andrew.'" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"What is my name?\")" + ] + }, + { + "cell_type": "markdown", + "id": "5a96a8d9", + "metadata": {}, + "source": [ + "#### 2.1.5 查看储存缓存\n", + "\n", + "储存缓存(memory.buffer)\n", + "储存了当前为止所有的对话信息" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "2529400d", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Human: Hi, my name is Andrew\n", + "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", + "Human: What is 1+1?\n", + "AI: 1+1 is equal to 2.\n", + "Human: What is my name?\n", + "AI: Your name is Andrew.\n" + ] + } + ], + "source": [ + "print(memory.buffer) " + ] + }, + { + "cell_type": "markdown", + "id": "0b5de846", + "metadata": {}, + "source": [ + "也可以通过memory.load_memory_variables({})打印缓存中的历史消息。这里的`{}`是一个空字典,有一些更高级的功能,使用户可以使用更复杂的输入,但我们不会在这个短期课程中讨论它们,所以不要担心为什么这里有一个空的花括号。" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "5018cb0a", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'history': \"Human: Hi, my name is Andrew\\nAI: Hello Andrew! It's nice to meet you. How can I assist you today?\\nHuman: What is 1+1?\\nAI: 1+1 is equal to 2.\\nHuman: What is my name?\\nAI: Your name is Andrew.\"}\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({}))" + ] + }, + { + "cell_type": "markdown", + "id": "07d2e892", + "metadata": {}, + "source": [ + "#### 2.1.6 直接添加内容到储存缓存" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "14219b70", + "metadata": { + "height": 31 + }, + "outputs": [], + "source": [ + "memory = ConversationBufferMemory() # 新建一个空的对话缓存记忆" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "a36e9905", + "metadata": { + "height": 48 + }, + "outputs": [], + "source": [ + "memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"}) # 向缓存区添加指定对话的输入输出" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "61631b1f", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Human: Hi\n", + "AI: What's up\n" + ] + } + ], + "source": [ + "print(memory.buffer) # 查看缓存区结果" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "a2fdf9ec", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'history': \"Human: Hi\\nAI: What's up\"}\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({}))# 再次加载记忆变量" + ] + }, + { + "cell_type": "markdown", + "id": "2ac544f2", + "metadata": {}, + "source": [ + "继续添加新的内容,对话历史都保存下来在了!" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "7ca79256", + "metadata": { + "height": 64 + }, + "outputs": [], + "source": [ + "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "890a4497", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': \"Human: Hi\\nAI: What's up\\nHuman: Not much, just hanging\\nAI: Cool\"}" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "6eddd91a-bf1c-4b82-b99c-c585420e4ecb", + "metadata": {}, + "source": [ + "### 2.2 中文版" + ] + }, + { + "cell_type": "markdown", + "id": "55b3e4e9-7a6a-4a09-9ac3-0096a67849c7", + "metadata": {}, + "source": [ + "#### 2.1.1 初始化对话模型" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "3577aaff-7edb-40b0-866a-e407e63d55e0", + "metadata": { + "height": 98 + }, + "outputs": [], + "source": [ + "from langchain.chains import ConversationChain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.memory import ConversationBufferMemory" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "a77d37ab-1f75-4ae8-8d7c-5066773ead81", + "metadata": { + "height": 133 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "\n", + "Human: 你好, 我叫皮皮鲁\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?'" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "llm = ChatOpenAI(temperature=0.0) \n", + "\n", + "memory = ConversationBufferMemory()\n", + "\n", + "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )" + ] + }, + { + "cell_type": "markdown", + "id": "747cb539-abc4-4e47-8cb9-1ee608ab07fc", + "metadata": {}, + "source": [ + "#### 2.1.2 第一轮对话" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99e48462-7a92-4842-bdaa-2a478ba2252c", + "metadata": {}, + "outputs": [], + "source": [ + "conversation.predict(input=\"你好, 我叫皮皮鲁\")" + ] + }, + { + "cell_type": "markdown", + "id": "979d320b-6b20-4722-99db-c48a43711d6c", + "metadata": {}, + "source": [ + "#### 2.1.3 第二轮对话" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "6ed6e97a-d7ea-4188-a6d7-f91d2a29d14a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "Human: 你好, 我叫皮皮鲁\n", + "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", + "Human: 1+1等于多少?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'1+1等于2。'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"1+1等于多少?\")" + ] + }, + { + "cell_type": "markdown", + "id": "8a1fd531-216e-42d8-b226-839747ad7dd3", + "metadata": {}, + "source": [ + "#### 2.1.4 第三轮对话" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5dfe488-2758-42c7-9c20-e483b4c22ab8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "Human: 你好, 我叫皮皮鲁\n", + "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", + "Human: 1+1等于多少?\n", + "AI: 1+1等于2。\n", + "Human: What is my name?\n", + "AI: 你的名字是皮皮鲁。\n", + "Human: 我叫什么名字?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'你叫皮皮鲁。'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"我叫什么名字?\")" + ] + }, + { + "cell_type": "markdown", + "id": "05d9822e-943d-4905-a1f8-a0d28c215d60", + "metadata": {}, + "source": [ + "#### 2.1.5 查看储存缓存" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "0795580f-b6b6-47e0-8882-26fe204560bd", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Human: 你好, 我叫皮皮鲁\n", + "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", + "Human: 1+1等于多少?\n", + "AI: 1+1等于2。\n", + "Human: What is my name?\n", + "AI: 你的名字是皮皮鲁。\n", + "Human: 我叫什么名字?\n", + "AI: 你叫皮皮鲁。\n" + ] + } + ], + "source": [ + "print(memory.buffer) " + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "dfe7824f-bd6e-4b95-92e2-1c85c62a92e9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Human: 你好, 我叫皮皮鲁\n", + "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", + "Human: 1+1等于多少?\n", + "AI: 1+1等于2。\n", + "Human: What is my name?\n", + "AI: 你的名字是皮皮鲁。\n", + "Human: 我叫什么名字?\n", + "AI: 你叫皮皮鲁。\n" + ] + } + ], + "source": [ + "print(memory.buffer) " + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "48942759-8afb-4aed-80c5-a48952a2b0c0", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'history': 'Human: 你好, 我叫皮皮鲁\\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\\nHuman: 1+1等于多少?\\nAI: 1+1等于2。\\nHuman: What is my name?\\nAI: 你的名字是皮皮鲁。\\nHuman: 我叫什么名字?\\nAI: 你叫皮皮鲁。'}\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({}))" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "4d0c4625-e928-45dc-b8da-4ab865ac5f7e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: 你好, 我叫皮皮鲁\\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\\nHuman: 1+1等于多少?\\nAI: 1+1等于2。\\nHuman: What is my name?\\nAI: 你的名字是皮皮鲁。\\nHuman: 我叫什么名字?\\nAI: 你叫皮皮鲁。'}" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "80f3778e-5fbf-43ed-9df1-d57d98ec6fb0", + "metadata": {}, + "source": [ + "#### 2.1.6 直接添加内容到储存缓存" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "147b2c30-1662-4b49-aaf8-c228428e5cc6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西'}" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory = ConversationBufferMemory()\n", + "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "6b5e27f0-dad7-41b6-9326-bebf6299638f", + "metadata": { + "height": 64 + }, + "outputs": [], + "source": [ + "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "cfa7c555-06ab-4906-b3dc-906f789e08f5", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool'}" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "deb33de8-37ea-4180-a73e-0fc456b14eb0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool\\nHuman: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "10146f1a-0114-4902-8122-d19ae6f7c461", + "metadata": {}, + "source": [ + "### 2.3 总结" + ] + }, + { + "cell_type": "markdown", + "id": "2759b6bc-edb2-4cfe-b0f8-1bf6c4d796f9", + "metadata": {}, + "source": [ + "当我们在使用大型语言模型进行聊天对话时,**大型语言模型本身实际上是无状态的。语言模型本身并不记得到目前为止的历史对话**。每次调用API结点都是独立的。储存(Memory)可以储存到目前为止的所有术语或对话,并将其输入或附加上下文到LLM中用于生成输出。如此看起来就好像它在进行下一轮对话的时候,记得之前说过什么。\n" + ] + }, + { + "cell_type": "markdown", + "id": "cf98e9ff", + "metadata": {}, + "source": [ + "## 三、对话缓存窗口储存\n", + " \n", + "随着对话变得越来越长,所需的内存量也变得非常长。将大量的tokens发送到LLM的成本,也会变得更加昂贵,这也就是为什么API的调用费用,通常是基于它需要处理的tokens数量而收费的。\n", + " \n", + "针对以上问题,LangChain也提供了几种方便的储存方式来保存历史对话。其中,对话缓存窗口储存只保留一个窗口大小的对话。它只使用最近的n次交互。这可以用于保持最近交互的滑动窗口,以便缓冲区不会过大" + ] + }, + { + "cell_type": "markdown", + "id": "b63c9061-9916-4524-b497-93a0aa2b7d06", + "metadata": {}, + "source": [ + "### 3.1 英文版" + ] + }, + { + "cell_type": "markdown", + "id": "641477a4", + "metadata": {}, + "source": [ + "#### 3.1.1 添加两轮对话到窗口储存" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "3ea6233e", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "from langchain.memory import ConversationBufferWindowMemory\n", + "\n", + "# k 为窗口参数,k=1表明只保留一个对话记忆\n", + "memory = ConversationBufferWindowMemory(k=1) " + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "dc4553fb", + "metadata": { + "height": 115 + }, + "outputs": [], + "source": [ + "# 向memory添加两轮对话\n", + "memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"})\n", + "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "6a788403", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: Not much, just hanging\\nAI: Cool'}" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 并查看记忆变量当前的记录\n", + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "63bda148", + "metadata": {}, + "source": [ + "#### 3.1.2 在对话链中应用窗口储存" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "4087bc87", + "metadata": { + "height": 133 + }, + "outputs": [], + "source": [ + "llm = ChatOpenAI(temperature=0.0)\n", + "memory = ConversationBufferWindowMemory(k=1)\n", + "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )" + ] + }, + { + "cell_type": "markdown", + "id": "b6d661e3", + "metadata": {}, + "source": [ + "注意此处!由于这里用的是一个窗口的记忆,因此只能保存一轮的历史消息,因此AI并不能知道你第一轮对话中提到的名字,他最多只能记住上一轮(第二轮)的对话信息" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "4faaa952", + "metadata": { + "height": 47 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\"Hello Andrew! It's nice to meet you. How can I assist you today?\"" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"Hi, my name is Andrew\")" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "bb20ddaa", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'1+1 is equal to 2.'" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"What is 1+1?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "489b2194", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\"I'm sorry, but I don't have access to personal information.\"" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"What is my name?\")" + ] + }, + { + "cell_type": "markdown", + "id": "88837e7c-cf4b-469e-b820-bbfc49ba876c", + "metadata": {}, + "source": [ + "### 3.2 中文版" + ] + }, + { + "cell_type": "markdown", + "id": "760ec3ad-6959-4a36-b1b5-4fcafe8088ad", + "metadata": {}, + "source": [ + "#### 3.1.1 添加两轮对话到窗口储存" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "68a2907c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'Human: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from langchain.memory import ConversationBufferWindowMemory\n", + "\n", + "# k=1表明只保留一个对话记忆\n", + "memory = ConversationBufferWindowMemory(k=1) \n", + "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", + "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "dcabf017-5bfd-4904-9f06-388f994eddc9", + "metadata": {}, + "source": [ + "#### 3.1.2 在对话链中应用窗口储存" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "1ee854d9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", + "1+1等于2。\n", + "很抱歉,我无法知道您的名字。\n" + ] + } + ], + "source": [ + "llm = ChatOpenAI(temperature=0.0)\n", + "memory = ConversationBufferWindowMemory(k=1)\n", + "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )\n", + "print(conversation.predict(input=\"你好, 我叫皮皮鲁\"))\n", + "print(conversation.predict(input=\"1+1等于多少?\"))\n", + "print(conversation.predict(input=\"我叫什么名字?\"))" + ] + }, + { + "cell_type": "markdown", + "id": "d2931b92", + "metadata": {}, + "source": [ + "## 四、对话token缓存储存" + ] + }, + { + "cell_type": "markdown", + "id": "dff5b4c7", + "metadata": {}, + "source": [ + "使用对话token缓存记忆,内存将限制保存的token数量。如果token数量超出指定数目,它会切掉这个对话的早期部分\n", + "以保留与最近的交流相对应的token数量,但不超过token限制。" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "9f6d063c", + "metadata": { + "height": 31 + }, + "outputs": [], + "source": [ + "!pip install -q tiktoken " + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "fb9020ed", + "metadata": { + "height": 81 + }, + "outputs": [], + "source": [ + "from langchain.llms import OpenAI\n", + "from langchain.memory import ConversationTokenBufferMemory" + ] + }, + { + "cell_type": "markdown", + "id": "f3a84112", + "metadata": {}, + "source": [ + "### 4.1 英文版\n", + "添加对话到Token缓存储存,限制token数量,进行测试" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "43582ee6", + "metadata": { + "height": 149 + }, + "outputs": [], + "source": [ + "memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", + "memory.save_context({\"input\": \"AI is what?!\"}, {\"output\": \"Amazing!\"})\n", + "memory.save_context({\"input\": \"Backpropagation is what?\"}, {\"output\": \"Beautiful!\"})\n", + "memory.save_context({\"input\": \"Chatbots are what?\"}, {\"output\": \"Charming!\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "284288e1", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'AI: Beautiful!\\nHuman: Chatbots are what?\\nAI: Charming!'}" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "7b62b2e1", + "metadata": {}, + "source": [ + "可以看到前面超出的的token已经被舍弃了!!!" + ] + }, + { + "cell_type": "markdown", + "id": "f7f6be43", + "metadata": {}, + "source": [ + "### 4.2 中文版" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "e9191020", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': 'AI: 轻舟已过万重山。'}" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", + "memory.save_context({\"input\": \"朝辞白帝彩云间,\"}, {\"output\": \"千里江陵一日还。\"})\n", + "memory.save_context({\"input\": \"两岸猿声啼不住,\"}, {\"output\": \"轻舟已过万重山。\"})\n", + "memory.load_memory_variables({})" + ] + }, + { + "cell_type": "markdown", + "id": "fb08ef4a-876f-422a-81f9-4805288e5955", + "metadata": {}, + "source": [ + "### 4.3 补充" + ] + }, + { + "cell_type": "markdown", + "id": "5e4d918b", + "metadata": {}, + "source": [ + "ChatGPT使用一种基于字节对编码(Byte Pair Encoding,BPE)的方法来进行tokenization(将输入文本拆分为token)。BPE是一种常见的tokenization技术,它将输入文本分割成较小的子词单元。 \n", + "\n", + "OpenAI在其官方GitHub上公开了一个最新的开源Python库 [tiktoken](https://github.com/openai/tiktoken),这个库主要是用来计算tokens数量的。相比较HuggingFace的tokenizer,其速度提升了好几倍。\n", + "\n", + "具体token计算方式,特别是汉字和英文单词的token区别,具体课参考[知乎文章](https://www.zhihu.com/question/594159910) 。" + ] + }, + { + "cell_type": "markdown", + "id": "5ff55d5d", + "metadata": {}, + "source": [ + "## 五、对话摘要缓存储存" + ] + }, + { + "cell_type": "markdown", + "id": "7d39b83a", + "metadata": {}, + "source": [ + "对话摘要缓存储存,**使用LLM编写到目前为止历史对话的摘要**,并将其保存" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "72dcf8b1", + "metadata": { + "height": 64 + }, + "outputs": [], + "source": [ + "from langchain.chains import ConversationChain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.memory import ConversationSummaryBufferMemory" + ] + }, + { + "cell_type": "markdown", + "id": "243b213e-ce17-46a0-8652-03658ca58dd8", + "metadata": {}, + "source": [ + "### 5.1 英文版" + ] + }, + { + "cell_type": "markdown", + "id": "6572ef39", + "metadata": {}, + "source": [ + "#### 5.1.1 使用对话摘要缓存储存\n", + "\n", + "创建一个长字符串,其中包含某人的日程安排" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "4a5b238f", + "metadata": { + "height": 285 + }, + "outputs": [], + "source": [ + "# 创建一个长字符串\n", + "schedule = \"There is a meeting at 8am with your product team. \\\n", + "You will need your powerpoint presentation prepared. \\\n", + "9am-12pm have time to work on your LangChain \\\n", + "project which will go quickly because Langchain is such a powerful tool. \\\n", + "At Noon, lunch at the italian resturant with a customer who is driving \\\n", + "from over an hour away to meet you to understand the latest in AI. \\\n", + "Be sure to bring your laptop to show the latest LLM demo.\"\n", + "\n", + "# 使用对话摘要缓存记忆\n", + "llm = ChatOpenAI(temperature=0.0)\n", + "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100) \n", + "memory.save_context({\"input\": \"Hello\"}, {\"output\": \"What's up\"})\n", + "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})\n", + "memory.save_context(\n", + " {\"input\": \"What is on the schedule today?\"}, {\"output\": f\"{schedule}\"}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "id": "15226a41-ab36-43a0-93f7-c03c6b374936", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({})['history'])" + ] + }, + { + "cell_type": "markdown", + "id": "7ccb97b6", + "metadata": {}, + "source": [ + "#### 5.1.2 基于对话摘要缓存储存的对话链\n", + "基于上面的对话摘要缓存储存,新建一个对话链" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "id": "6728edba", + "metadata": { + "height": 99 + }, + "outputs": [], + "source": [ + "conversation = ConversationChain(llm=llm, memory=memory, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "id": "9a221b1d", + "metadata": { + "height": 47 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n", + "Human: What would be a good demo to show?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.'" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"What would be a good demo to show?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "id": "bb582617", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting. A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({})['history'])" + ] + }, + { + "cell_type": "markdown", + "id": "4ba827aa", + "metadata": { + "height": 31 + }, + "source": [ + "### 5.2 中文版" + ] + }, + { + "cell_type": "markdown", + "id": "64898f33-c538-4e68-b008-7123870b692b", + "metadata": {}, + "source": [ + "#### 5.2.1 使用对话摘要缓存储存\n", + "\n", + "创建一个长字符串,其中包含某人的日程安排" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "2c07922b", + "metadata": { + "height": 31 + }, + "outputs": [], + "source": [ + "# 创建一个长字符串\n", + "schedule = \"在八点你和你的产品团队有一个会议。 \\\n", + "你需要做一个PPT。 \\\n", + "上午9点到12点你需要忙于LangChain。\\\n", + "Langchain是一个有用的工具,因此你的项目进展的非常快。\\\n", + "中午,在意大利餐厅与一位开车来的顾客共进午餐 \\\n", + "走了一个多小时的路程与你见面,只为了解最新的 AI。 \\\n", + "确保你带了笔记本电脑可以展示最新的 LLM 样例.\"\n", + "\n", + "llm = ChatOpenAI(temperature=0.0)\n", + "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)\n", + "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", + "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", + "memory.save_context({\"input\": \"今天的日程安排是什么?\"}, {\"output\": f\"{schedule}\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "17424a12-430f-4529-9067-300978c6169e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n" + ] + } + ], + "source": [ + "print(memory.load_memory_variables({})['history'])" + ] + }, + { + "cell_type": "markdown", + "id": "9e29a956-607a-4247-9eb5-01285a370991", + "metadata": {}, + "source": [ + "#### 5.1.2 基于对话摘要缓存储存的对话链\n", + "基于上面的对话摘要缓存储存,新建一个对话链" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "id": "52696c8c", + "metadata": { + "height": 31 + }, + "outputs": [], + "source": [ + "conversation = ConversationChain(llm=llm, memory=memory, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "id": "48690d13", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", + "\n", + "Current conversation:\n", + "System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n", + "Human: 展示什么样的样例最好呢?\n", + "AI:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'展示一些具有多样性和创新性的样例可能是最好的选择。你可以选择展示一些基于图像识别的样例,比如人脸识别、物体识别等。另外,你也可以展示一些自然语言处理方面的样例,比如文本生成、情感分析等。最重要的是选择那些能够展示出你们团队的技术实力和创造力的样例。'" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conversation.predict(input=\"展示什么样的样例最好呢?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "id": "85bba1f8", + "metadata": { + "height": 31 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'history': \"System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples. The human asks what kind of samples would be best to showcase. The AI suggests that showcasing diverse and innovative samples would be the best choice. They recommend selecting samples based on image recognition, such as face recognition and object recognition. Additionally, they suggest showcasing samples related to natural language processing, such as text generation and sentiment analysis. The AI emphasizes the importance of choosing samples that demonstrate the team's technical expertise and creativity.\"}" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "memory.load_memory_variables({}) # 摘要记录更新了" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/content/LangChain for LLM Application Development/3.存储 Memory.ipynb b/content/LangChain for LLM Application Development/3.存储 Memory.ipynb deleted file mode 100644 index 6efeba6..0000000 --- a/content/LangChain for LLM Application Development/3.存储 Memory.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"cells":[{"cell_type":"markdown","id":"a786c77c","metadata":{"jp-MarkdownHeadingCollapsed":true,"tags":[]},"source":["# 第三章 储存\n","\n"," - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n"," - [二、对话缓存储存 ](#二、对话缓存储存--)\n"," - [2.1 开始对话,第一轮](#2.1-开始对话,第一轮)\n"," - [2.2 第二轮对话](#2.2-第二轮对话)\n"," - [2.3 第三轮对话](#2.3-第三轮对话)\n"," - [2.4 .memory.buffer存储了当前为止所有的对话信息](#2.4-.memory.buffer存储了当前为止所有的对话信息)\n"," - [2.5 也可以通过memory.load_memory_variables({})打印历史消息](#2.5-也可以通过memory.load_memory_variables({})打印历史消息)\n"," - [2.6 添加指定的输入输出内容到记忆缓存区](#2.6-添加指定的输入输出内容到记忆缓存区)\n"," - [三、对话缓存窗口储存](#三、对话缓存窗口储存)\n"," - [3.1 向memory添加两轮对话,并查看记忆变量当前的记录](#3.1-向memory添加两轮对话,并查看记忆变量当前的记录)\n"," - [3.2 在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆](#3.2-在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆)\n"," - [3.3 将对话缓存窗口记忆应用到对话链中](#3.3-将对话缓存窗口记忆应用到对话链中)\n"," - [四、对话token缓存储存](#四、对话token缓存储存)\n"," - [4.1 导入相关包和API密钥](#4.1-导入相关包和API密钥)\n"," - [4.2 限制token数量,进行测试](#4.2-限制token数量,进行测试)\n"," - [4.3 中文例子](#4.3-中文例子)\n"," - [五、对话摘要缓存储存](#五、对话摘要缓存储存)\n"," - [5.1 创建一个长字符串,其中包含某人的日程安排](#5.1-创建一个长字符串,其中包含某人的日程安排)\n"," - [5.2 基于上面的memory,新建一个对话链](#5.2-基于上面的memory,新建一个对话链)\n"," - [5.3 中文例子](#5.3-中文例子)\n"]},{"cell_type":"markdown","id":"7e10db6f","metadata":{},"source":["当你与那些语言模型进行交互的时候,他们不会记得你之前和他进行的交流内容,这在我们构建一些应用程序(如聊天机器人)的时候,是一个很大的问题---显得不够智能!因此,在本节中我们将介绍 LangChain 中的储存模块,即如何将先前的对话嵌入到语言模型中的,使其具有连续对话的能力。\n","\n","当使用 LangChain 中的储存模块时,它可以帮助保存和管理历史聊天消息,以及构建关于特定实体的知识。这些组件可以跨多轮对话存储信息,并允许在对话期间跟踪特定信息和上下文。LangChain 提供了多种储存类型。其中,缓冲区储存允许保留最近的聊天消息,摘要储存则提供了对整个对话的摘要。实体储存则允许在多轮对话中保留有关特定实体的信息。这些记忆组件都是模块化的,可与其他组件组合使用,从而增强机器人的对话管理能力。储存模块可以通过简单的API调用来访问和更新,允许开发人员更轻松地实现对话历史记录的管理和维护。\n","\n","此次课程主要介绍其中四种记忆模块,其他模块可查看文档学习。\n","- 对话缓存记忆 (ConversationBufferMemory)\n","- 对话缓存窗口记忆 (ConversationBufferWindowMemory)\n","- 对话令牌缓存记忆 (ConversationTokenBufferMemory)\n","- 对话摘要缓存记忆 (ConversationSummaryBufferMemory)\n","\n","在LangChain中,Memory指的是大语言模型(LLM)的短期记忆。为什么是短期记忆?那是因为LLM训练好之后(获得了一些长期记忆),它的参数便不会因为用户的输入而发生改变。当用户与训练好的LLM进行对话时,LLM会暂时记住用户的输入和它已经生成的输出,以便预测之后的输出,而模型输出完毕后,它便会“遗忘”之前用户的输入和它的输出。因此,之前的这些信息只能称作为LLM的短期记忆。 \n"," \n","为了延长LLM短期记忆的保留时间,则需要借助一些外部存储方式来进行记忆,以便在用户与LLM对话中,LLM能够尽可能的知道用户与它所进行的历史对话信息。 "]},{"cell_type":"markdown","id":"1ca56e6b-1e07-4405-a1ca-f4237f20fa75","metadata":{"tags":[]},"source":["## 一、设置OpenAI API Key\n","\n","登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n","\n","- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n","- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n","\n","

\n"," OPENAI_API_KEY=\"your_api_key\" \n","

\n"," \n"," 替换\"your_api_key\"为你自己的 API Key"]},{"cell_type":"code","execution_count":null,"id":"6932bd47-c6d5-4794-8102-a12b84412a93","metadata":{},"outputs":[],"source":["# 下载需要的包python-dotenv和openai\n","# 如果你需要查看安装过程日志,可删除 -q \n","!pip install -q python-dotenv\n","!pip install -q openai"]},{"cell_type":"code","execution_count":6,"id":"10446712-9fa6-4d71-94ce-2ea4cf197e54","metadata":{},"outputs":[],"source":["import os\n","import openai\n","from dotenv import load_dotenv, find_dotenv\n","\n","# 读取本地/项目的环境变量。\n","\n","# find_dotenv()寻找并定位.env文件的路径\n","# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中 \n","# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n","_ = load_dotenv(find_dotenv())\n","\n","# 获取环境变量 OPENAI_API_KEY\n","openai.api_key = os.environ['OPENAI_API_KEY'] \n"]},{"cell_type":"markdown","id":"1297dcd5","metadata":{},"source":["## 二、对话缓存储存 \n"," \n","这种记忆允许存储消息,然后从变量中提取消息。"]},{"cell_type":"code","execution_count":2,"id":"20ad6fe2","metadata":{"height":98},"outputs":[],"source":["from langchain.chat_models import ChatOpenAI\n","from langchain.chains import ConversationChain\n","from langchain.memory import ConversationBufferMemory"]},{"cell_type":"code","execution_count":31,"id":"88bdf13d","metadata":{"height":133},"outputs":[],"source":["# 英文链\n","llm = ChatOpenAI(temperature=0.0) #temperature:预测下一个token时,概率越大的值就越平滑(平滑也就是让差异大的值之间的差异变得没那么大),temperature值越小则生成的内容越稳定\n","memory = ConversationBufferMemory()\n","conversation = ConversationChain( #新建一个对话链(关于链后面会提到更多的细节)\n"," llm=llm, \n"," memory = memory,\n"," verbose=True #查看Langchain实际上在做什么,设为FALSE的话只给出回答,看到不到下面绿色的内容\n",")"]},{"cell_type":"code","execution_count":32,"id":"bb4968d9","metadata":{},"outputs":[],"source":["# 中文链\n","llm = ChatOpenAI(temperature=0.0) #temperature:预测下一个token时,概率越大的值就越平滑(平滑也就是让差异大的值之间的差异变得没那么大),temperature值越小则生成的内容越稳定\n","memory_zh = ConversationBufferMemory()\n","conversation_zh = ConversationChain( #新建一个对话链(关于链后面会提到更多的细节)\n"," llm=llm, \n"," memory = memory_zh,\n"," verbose=True #查看Langchain实际上在做什么,设为FALSE的话只给出回答,看到不到下面绿色的内容\n",")"]},{"cell_type":"markdown","id":"dea83837","metadata":{},"source":["### 2.1 开始对话,第一轮"]},{"cell_type":"markdown","id":"1a3b4c42","metadata":{},"source":["当我们运行predict时,生成了一些提示,如下所见,他说“以下是人类和AI之间友好的对话,AI健谈“等等,这实际上是LangChain生成的提示,以使系统进行希望和友好的对话,并且必须保存对话,并提示了当前已完成的模型链。"]},{"cell_type":"code","execution_count":33,"id":"db24677d","metadata":{"height":47},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","\n","Human: Hi, my name is Andrew\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["\"Hello Andrew! It's nice to meet you. How can I assist you today?\""]},"execution_count":33,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"Hi, my name is Andrew\")"]},{"cell_type":"code","execution_count":34,"id":"154561c9","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","\n","Human: 你好, 我叫皮皮鲁\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?'"]},"execution_count":34,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","conversation_zh.predict(input=\"你好, 我叫皮皮鲁\")"]},{"cell_type":"markdown","id":"e71564ad","metadata":{},"source":["### 2.2 第二轮对话"]},{"cell_type":"markdown","id":"54d006bd","metadata":{},"source":["当我们进行下一轮对话时,他会保留上面的提示"]},{"cell_type":"code","execution_count":35,"id":"cc3ef937","metadata":{"height":31},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","Human: Hi, my name is Andrew\n","AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n","Human: What is 1+1?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'1+1 is equal to 2.'"]},"execution_count":35,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"What is 1+1?\")"]},{"cell_type":"code","execution_count":36,"id":"63efc1bb","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","Human: 你好, 我叫皮皮鲁\n","AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n","Human: 1+1等于多少?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'1+1等于2。'"]},"execution_count":36,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","conversation_zh.predict(input=\"1+1等于多少?\")"]},{"cell_type":"markdown","id":"33cb734b","metadata":{},"source":["### 2.3 第三轮对话"]},{"cell_type":"markdown","id":"0393df3d","metadata":{},"source":["为了验证他是否记忆了前面的对话内容,我们让他回答前面已经说过的内容(我的名字),可以看到他确实输出了正确的名字,因此这个对话链随着往下进行会越来越长"]},{"cell_type":"code","execution_count":37,"id":"acf3339a","metadata":{"height":31},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","Human: Hi, my name is Andrew\n","AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n","Human: What is 1+1?\n","AI: 1+1 is equal to 2.\n","Human: What is my name?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'Your name is Andrew.'"]},"execution_count":37,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"What is my name?\")"]},{"cell_type":"code","execution_count":38,"id":"2206e5b7","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","Human: 你好, 我叫皮皮鲁\n","AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n","Human: 1+1等于多少?\n","AI: 1+1等于2。\n","Human: 我叫什么名字?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'你叫皮皮鲁。'"]},"execution_count":38,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","conversation_zh.predict(input=\"我叫什么名字?\")"]},{"cell_type":"markdown","id":"5a96a8d9","metadata":{},"source":["### 2.4 .memory.buffer存储了当前为止所有的对话信息"]},{"cell_type":"code","execution_count":39,"id":"2529400d","metadata":{"height":31},"outputs":[{"name":"stdout","output_type":"stream","text":["Human: Hi, my name is Andrew\n","AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n","Human: What is 1+1?\n","AI: 1+1 is equal to 2.\n","Human: What is my name?\n","AI: Your name is Andrew.\n"]}],"source":["print(memory.buffer) #提取历史消息"]},{"cell_type":"code","execution_count":40,"id":"d948aeb2","metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Human: 你好, 我叫皮皮鲁\n","AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n","Human: 1+1等于多少?\n","AI: 1+1等于2。\n","Human: 我叫什么名字?\n","AI: 你叫皮皮鲁。\n"]}],"source":["# 中文\n","print(memory_zh.buffer) #提取历史消息"]},{"cell_type":"markdown","id":"6bd222c3","metadata":{},"source":["### 2.5 也可以通过memory.load_memory_variables({})打印历史消息"]},{"cell_type":"markdown","id":"0b5de846","metadata":{},"source":["这里的花括号实际上是一个空字典,有一些更高级的功能,使用户可以使用更复杂的输入,但我们不会在这个短期课程中讨论它们,所以不要担心为什么这里有一个空的花括号。"]},{"cell_type":"code","execution_count":41,"id":"5018cb0a","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': \"Human: Hi, my name is Andrew\\nAI: Hello Andrew! It's nice to meet you. How can I assist you today?\\nHuman: What is 1+1?\\nAI: 1+1 is equal to 2.\\nHuman: What is my name?\\nAI: Your name is Andrew.\"}"]},"execution_count":41,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({})"]},{"cell_type":"code","execution_count":42,"id":"af4b8b12","metadata":{},"outputs":[{"data":{"text/plain":["{'history': 'Human: 你好, 我叫皮皮鲁\\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\\nHuman: 1+1等于多少?\\nAI: 1+1等于2。\\nHuman: 我叫什么名字?\\nAI: 你叫皮皮鲁。'}"]},"execution_count":42,"metadata":{},"output_type":"execute_result"}],"source":["# 中文\n","memory_zh.load_memory_variables({})"]},{"cell_type":"markdown","id":"07d2e892","metadata":{},"source":["### 2.6 添加指定的输入输出内容到记忆缓存区"]},{"cell_type":"code","execution_count":43,"id":"14219b70","metadata":{"height":31},"outputs":[],"source":["memory = ConversationBufferMemory() #新建一个空的对话缓存记忆"]},{"cell_type":"code","execution_count":45,"id":"a36e9905","metadata":{"height":48},"outputs":[],"source":["memory.save_context({\"input\": \"Hi\"}, #向缓存区添加指定对话的输入输出\n"," {\"output\": \"What's up\"})"]},{"cell_type":"code","execution_count":46,"id":"61631b1f","metadata":{"height":31},"outputs":[{"name":"stdout","output_type":"stream","text":["Human: Hi\n","AI: What's up\n","Human: Hi\n","AI: What's up\n"]}],"source":["print(memory.buffer) #查看缓存区结果"]},{"cell_type":"code","execution_count":47,"id":"a2fdf9ec","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': \"Human: Hi\\nAI: What's up\\nHuman: Hi\\nAI: What's up\"}"]},"execution_count":47,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({}) #再次加载记忆变量"]},{"cell_type":"code","execution_count":48,"id":"27d8dd2f","metadata":{},"outputs":[{"data":{"text/plain":["{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西'}"]},"execution_count":48,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","memory = ConversationBufferMemory()\n","memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, \n"," {\"output\": \"你好啊,我叫鲁西西\"})\n","memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"2ac544f2","metadata":{},"source":["继续添加新的内容,对话历史都保存下来在了!"]},{"cell_type":"code","execution_count":49,"id":"7ca79256","metadata":{"height":64},"outputs":[],"source":["memory.save_context({\"input\": \"Not much, just hanging\"}, \n"," {\"output\": \"Cool\"})"]},{"cell_type":"code","execution_count":50,"id":"890a4497","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool'}"]},"execution_count":50,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({})"]},{"cell_type":"code","execution_count":51,"id":"2b614406","metadata":{},"outputs":[{"data":{"text/plain":["{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool\\nHuman: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}"]},"execution_count":51,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, \n"," {\"output\": \"是的,让我们一起去冒险吧!\"})\n","memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"8839314a","metadata":{},"source":["当我们在使用大型语言模型进行聊天对话时,**大型语言模型本身实际上是无状态的。语言模型本身并不记得到目前为止的历史对话**。每次调用API结点都是独立的。\n","\n","聊天机器人似乎有记忆,只是因为通常有快速的代码可以向LLM提供迄今为止的完整对话以及上下文。因此,Memory可以明确地存储到目前为止的所有术语或对话。这个Memory存储器被用作输入或附加上下文到LLM中,以便它可以生成一个输出,就好像它只有在进行下一轮对话的时候,才知道之前说过什么。\n"]},{"cell_type":"markdown","id":"cf98e9ff","metadata":{},"source":["## 三、对话缓存窗口储存\n"," \n","随着对话变得越来越长,所需的内存量也变得非常长。将大量的tokens发送到LLM的成本,也会变得更加昂贵,这也就是为什么API的调用费用,通常是基于它需要处理的tokens数量而收费的。\n"," \n","针对以上问题,LangChain也提供了几种方便的memory来保存历史对话。\n","其中,对话缓存窗口记忆只保留一个窗口大小的对话缓存区窗口记忆。它只使用最近的n次交互。这可以用于保持最近交互的滑动窗口,以便缓冲区不会过大"]},{"cell_type":"code","execution_count":52,"id":"66eeccc3","metadata":{"height":47},"outputs":[],"source":["from langchain.memory import ConversationBufferWindowMemory"]},{"cell_type":"markdown","id":"641477a4","metadata":{},"source":["### 3.1 向memory添加两轮对话,并查看记忆变量当前的记录"]},{"cell_type":"code","execution_count":53,"id":"3ea6233e","metadata":{"height":47},"outputs":[],"source":["memory = ConversationBufferWindowMemory(k=1) # k=1表明只保留一个对话记忆 "]},{"cell_type":"code","execution_count":54,"id":"dc4553fb","metadata":{"height":115},"outputs":[],"source":["memory.save_context({\"input\": \"Hi\"},\n"," {\"output\": \"What's up\"})\n","memory.save_context({\"input\": \"Not much, just hanging\"},\n"," {\"output\": \"Cool\"})\n"]},{"cell_type":"code","execution_count":55,"id":"6a788403","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': 'Human: Not much, just hanging\\nAI: Cool'}"]},"execution_count":55,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"9b401f0b","metadata":{},"source":["### 3.2 在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆"]},{"cell_type":"code","execution_count":56,"id":"68a2907c","metadata":{},"outputs":[{"data":{"text/plain":["{'history': 'Human: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}"]},"execution_count":56,"metadata":{},"output_type":"execute_result"}],"source":["#中文\n","memory = ConversationBufferWindowMemory(k=1) # k=1表明只保留一个对话记忆 \n","memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, \n"," {\"output\": \"你好啊,我叫鲁西西\"})\n","memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, \n"," {\"output\": \"是的,让我们一起去冒险吧!\"})\n","memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"63bda148","metadata":{},"source":["### 3.3 将对话缓存窗口记忆应用到对话链中"]},{"cell_type":"code","execution_count":57,"id":"4087bc87","metadata":{"height":133},"outputs":[],"source":["llm = ChatOpenAI(temperature=0.0)\n","memory = ConversationBufferWindowMemory(k=1)\n","conversation = ConversationChain( \n"," llm=llm, \n"," memory = memory,\n"," verbose=False #这里改为FALSE不显示提示,你可以尝试修改为TRUE后的结果\n",")"]},{"cell_type":"code","execution_count":61,"id":"0c737101","metadata":{},"outputs":[],"source":["# 中文版\n","llm = ChatOpenAI(temperature=0.0)\n","memory_zh = ConversationBufferWindowMemory(k=1)\n","conversation_zh = ConversationChain( \n"," llm=llm, \n"," memory = memory_zh,\n"," verbose=False #这里改为FALSE不显示提示,你可以尝试修改为TRUE后的结果\n",")"]},{"cell_type":"markdown","id":"b6d661e3","metadata":{},"source":["注意此处!由于这里用的是一个窗口的记忆,因此只能保存一轮的历史消息,因此AI并不能知道你第一轮对话中提到的名字,他最多只能记住上一轮(第二轮)的对话信息"]},{"cell_type":"code","execution_count":58,"id":"4faaa952","metadata":{"height":47},"outputs":[{"data":{"text/plain":["\"Hello Andrew! It's nice to meet you. How can I assist you today?\""]},"execution_count":58,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"Hi, my name is Andrew\")"]},{"cell_type":"code","execution_count":63,"id":"b3a941b5","metadata":{},"outputs":[{"data":{"text/plain":["'你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?'"]},"execution_count":63,"metadata":{},"output_type":"execute_result"}],"source":["conversation_zh.predict(input=\"你好,我是皮皮鲁\")"]},{"cell_type":"code","execution_count":64,"id":"bb20ddaa","metadata":{"height":31},"outputs":[{"data":{"text/plain":["'1+1 is equal to 2.'"]},"execution_count":64,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"What is 1+1?\")"]},{"cell_type":"code","execution_count":65,"id":"90bf6403","metadata":{},"outputs":[{"data":{"text/plain":["'1+1等于2。'"]},"execution_count":65,"metadata":{},"output_type":"execute_result"}],"source":["conversation_zh.predict(input=\"1+1等于几\")"]},{"cell_type":"code","execution_count":66,"id":"489b2194","metadata":{"height":31},"outputs":[{"data":{"text/plain":["\"I'm sorry, but I don't have access to personal information.\""]},"execution_count":66,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"What is my name?\")"]},{"cell_type":"code","execution_count":67,"id":"932ace4f","metadata":{},"outputs":[{"data":{"text/plain":["'很抱歉,我无法知道您的名字。'"]},"execution_count":67,"metadata":{},"output_type":"execute_result"}],"source":["conversation_zh.predict(input=\"我叫什么名字\")"]},{"cell_type":"markdown","id":"d2931b92","metadata":{},"source":["## 四、对话token缓存储存"]},{"cell_type":"markdown","id":"dff5b4c7","metadata":{},"source":["使用对话token缓存记忆,内存将限制保存的token数量。如果token数量超出指定数目,它会切掉这个对话的早期部分\n","以保留与最近的交流相对应的token数量,但不超过token限制。"]},{"cell_type":"code","execution_count":null,"id":"9f6d063c","metadata":{"height":31},"outputs":[],"source":["#!pip install tiktoken #需要用到tiktoken包,没有的可以先安装一下"]},{"cell_type":"markdown","id":"2187cfe6","metadata":{},"source":["### 4.1 导入相关包和API密钥"]},{"cell_type":"code","execution_count":68,"id":"fb9020ed","metadata":{"height":81},"outputs":[],"source":["from langchain.memory import ConversationTokenBufferMemory\n","from langchain.llms import OpenAI\n","\n","llm = ChatOpenAI(temperature=0.0)"]},{"cell_type":"markdown","id":"f3a84112","metadata":{},"source":["### 4.2 限制token数量,进行测试"]},{"cell_type":"code","execution_count":69,"id":"43582ee6","metadata":{"height":149},"outputs":[],"source":["memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n","memory.save_context({\"input\": \"AI is what?!\"},\n"," {\"output\": \"Amazing!\"})\n","memory.save_context({\"input\": \"Backpropagation is what?\"},\n"," {\"output\": \"Beautiful!\"})\n","memory.save_context({\"input\": \"Chatbots are what?\"}, \n"," {\"output\": \"Charming!\"})"]},{"cell_type":"markdown","id":"7b62b2e1","metadata":{},"source":["可以看到前面超出的的token已经被舍弃了!!!"]},{"cell_type":"code","execution_count":70,"id":"284288e1","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': 'AI: Beautiful!\\nHuman: Chatbots are what?\\nAI: Charming!'}"]},"execution_count":70,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"f7f6be43","metadata":{},"source":["### 4.3 中文例子"]},{"cell_type":"code","execution_count":71,"id":"e9191020","metadata":{},"outputs":[{"data":{"text/plain":["{'history': 'AI: 轻舟已过万重山。'}"]},"execution_count":71,"metadata":{},"output_type":"execute_result"}],"source":["memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n","memory.save_context({\"input\": \"朝辞白帝彩云间,\"}, \n"," {\"output\": \"千里江陵一日还。\"})\n","memory.save_context({\"input\": \"两岸猿声啼不住,\"},\n"," {\"output\": \"轻舟已过万重山。\"})\n","memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"5e4d918b","metadata":{},"source":["补充: \n","\n","ChatGPT使用一种基于字节对编码(Byte Pair Encoding,BPE)的方法来进行tokenization(将输入文本拆分为token)。 \n","BPE是一种常见的tokenization技术,它将输入文本分割成较小的子词单元。 \n","\n","OpenAI在其官方GitHub上公开了一个最新的开源Python库:tiktoken,这个库主要是用来计算tokens数量的。相比较Hugging Face的tokenizer,其速度提升了好几倍 \n","\n","具体token计算方式,特别是汉字和英文单词的token区别,参考 \n"]},{"cell_type":"markdown","id":"5ff55d5d","metadata":{},"source":["## 五、对话摘要缓存储存"]},{"cell_type":"markdown","id":"7d39b83a","metadata":{},"source":["这种Memory的想法是,不是将内存限制为基于最近对话的固定数量的token或固定数量的对话次数窗口,而是**使用LLM编写到目前为止历史对话的摘要**,并将其保存"]},{"cell_type":"code","execution_count":72,"id":"72dcf8b1","metadata":{"height":64},"outputs":[],"source":["from langchain.memory import ConversationSummaryBufferMemory\n","from langchain.chat_models import ChatOpenAI\n","from langchain.chains import ConversationChain"]},{"cell_type":"code","execution_count":73,"id":"c11d81c5","metadata":{},"outputs":[],"source":["llm = ChatOpenAI(temperature=0.0)"]},{"cell_type":"markdown","id":"6572ef39","metadata":{},"source":["### 5.1 创建一个长字符串,其中包含某人的日程安排"]},{"cell_type":"code","execution_count":74,"id":"4a5b238f","metadata":{"height":285},"outputs":[],"source":["# create a long string\n","schedule = \"There is a meeting at 8am with your product team. \\\n","You will need your powerpoint presentation prepared. \\\n","9am-12pm have time to work on your LangChain \\\n","project which will go quickly because Langchain is such a powerful tool. \\\n","At Noon, lunch at the italian resturant with a customer who is driving \\\n","from over an hour away to meet you to understand the latest in AI. \\\n","Be sure to bring your laptop to show the latest LLM demo.\"\n","\n","memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100) #使用对话摘要缓存记忆\n","memory.save_context({\"input\": \"Hello\"}, {\"output\": \"What's up\"})\n","memory.save_context({\"input\": \"Not much, just hanging\"},\n"," {\"output\": \"Cool\"})\n","memory.save_context({\"input\": \"What is on the schedule today?\"}, \n"," {\"output\": f\"{schedule}\"})"]},{"cell_type":"code","execution_count":75,"id":"2e4ecabe","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': 'System: The human and AI exchange greetings. The human mentions that they are not doing much. The AI informs the human about their schedule for the day, including a meeting with the product team, working on the LangChain project, and having lunch with a customer to discuss the latest in AI. The AI also reminds the human to bring their laptop to show a demo.'}"]},"execution_count":75,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({})"]},{"cell_type":"markdown","id":"7ccb97b6","metadata":{},"source":["### 5.2 基于上面的memory,新建一个对话链"]},{"cell_type":"code","execution_count":76,"id":"6728edba","metadata":{"height":99},"outputs":[],"source":["conversation = ConversationChain( \n"," llm=llm, \n"," memory = memory,\n"," verbose=True\n",")"]},{"cell_type":"code","execution_count":77,"id":"9a221b1d","metadata":{"height":47},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","System: The human and AI exchange greetings. The human mentions that they are not doing much. The AI informs the human about their schedule for the day, including a meeting with the product team, working on the LangChain project, and having lunch with a customer to discuss the latest in AI. The AI also reminds the human to bring their laptop to show a demo.\n","Human: What would be a good demo to show?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'A good demo to show would be a live demonstration of the LangChain project. You can showcase the features and functionality of the language translation software, highlighting its accuracy and efficiency. Additionally, you could also demonstrate any recent updates or improvements made to the project. This would give the customer a firsthand experience of the capabilities of the AI technology and its potential benefits for their business.'"]},"execution_count":77,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"What would be a good demo to show?\")"]},{"cell_type":"code","execution_count":78,"id":"bb582617","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': 'System: The human and AI exchange greetings. The human mentions that they are not doing much. The AI informs the human about their schedule for the day, including a meeting with the product team, working on the LangChain project, and having lunch with a customer to discuss the latest in AI. The AI also reminds the human to bring their laptop to show a demo.\\nHuman: What would be a good demo to show?\\nAI: A good demo to show would be a live demonstration of the LangChain project. You can showcase the features and functionality of the language translation software, highlighting its accuracy and efficiency. Additionally, you could also demonstrate any recent updates or improvements made to the project. This would give the customer a firsthand experience of the capabilities of the AI technology and its potential benefits for their business.'}"]},"execution_count":78,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({}) #摘要记录更新了"]},{"cell_type":"markdown","id":"4ba827aa","metadata":{"height":31},"source":["### 5.3 中文例子"]},{"cell_type":"code","execution_count":79,"id":"2c07922b","metadata":{"height":31},"outputs":[],"source":["# 创建一个长字符串\n","schedule = \"在八点你和你的产品团队有一个会议。 \\\n","你需要做一个PPT。 \\\n","上午9点到12点你需要忙于LangChain。\\\n","Langchain是一个有用的工具,因此你的项目进展的非常快。\\\n","中午,在意大利餐厅与一位开车来的顾客共进午餐 \\\n","走了一个多小时的路程与你见面,只为了解最新的 AI。 \\\n","确保你带了笔记本电脑可以展示最新的 LLM 样例.\"\n","\n","memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)\n","memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, \n"," {\"output\": \"你好啊,我叫鲁西西\"})\n","memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, \n"," {\"output\": \"是的,让我们一起去冒险吧!\"})\n","memory.save_context({\"input\": \"今天的日程安排是什么?\"}, \n"," {\"output\": f\"{schedule}\"})"]},{"cell_type":"code","execution_count":80,"id":"52696c8c","metadata":{"height":31},"outputs":[],"source":["conversation = ConversationChain( \n"," llm=llm, \n"," memory = memory,\n"," verbose=True\n",")"]},{"cell_type":"code","execution_count":81,"id":"48690d13","metadata":{"height":31},"outputs":[{"name":"stdout","output_type":"stream","text":["\n","\n","\u001b[1m> Entering new chain...\u001b[0m\n","Prompt after formatting:\n","\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n","\n","Current conversation:\n","System: The human and AI introduce themselves and become friends. They plan to go on an adventure together. The human asks about their schedule for the day. The AI informs the human about a meeting with their product team at 8 am and the need to prepare a PowerPoint presentation. From 9 am to 12 pm, the human will be busy with LangChain, a useful tool that will help their project progress quickly. At noon, they will have lunch with a customer who has traveled a long way to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n","Human: 展示什么样的样例最好呢?\n","AI:\u001b[0m\n","\n","\u001b[1m> Finished chain.\u001b[0m\n"]},{"data":{"text/plain":["'展示一些具有多样性和创新性的样例可能是最好的选择。你可以展示一些基于图像识别的样例,比如人脸识别、物体识别等。另外,你也可以展示一些自然语言处理方面的样例,比如文本生成、情感分析等。最好选择一些能够展示出你们团队的技术实力和创造力的样例。'"]},"execution_count":81,"metadata":{},"output_type":"execute_result"}],"source":["conversation.predict(input=\"展示什么样的样例最好呢?\")"]},{"cell_type":"code","execution_count":82,"id":"85bba1f8","metadata":{"height":31},"outputs":[{"data":{"text/plain":["{'history': \"System: The human and AI introduce themselves and become friends. They plan to go on an adventure together. The human asks about their schedule for the day. The AI informs the human about a meeting with their product team at 8 am and the need to prepare a PowerPoint presentation. From 9 am to 12 pm, the human will be busy with LangChain, a useful tool that will help their project progress quickly. At noon, they will have lunch with a customer who has traveled a long way to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples. The human asks what kind of samples would be best to showcase. The AI suggests that showcasing diverse and innovative samples would be the best choice. They recommend demonstrating examples based on image recognition, such as face recognition and object recognition. Additionally, they suggest showcasing examples in natural language processing, such as text generation and sentiment analysis. It is important to choose samples that demonstrate the team's technical expertise and creativity.\"}"]},"execution_count":82,"metadata":{},"output_type":"execute_result"}],"source":["memory.load_memory_variables({}) #摘要记录更新了"]}],"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":false,"sideBar":true,"skip_h1_title":false,"title_cell":"","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} From bc7bec2d5f392bd949131fa76a620367fa3a4733 Mon Sep 17 00:00:00 2001 From: joyenjoye Date: Sun, 16 Jul 2023 15:34:37 +0800 Subject: [PATCH 2/5] Update Chapter 2 and 3 --- ...解析器 Models, Prompts and Output Parsers.ipynb | 2 +- .../3.储存 Memory.ipynb | 1698 +---------------- 2 files changed, 2 insertions(+), 1698 deletions(-) diff --git a/content/LangChain for LLM Application Development/2.模型、提示和解析器 Models, Prompts and Output Parsers.ipynb b/content/LangChain for LLM Application Development/2.模型、提示和解析器 Models, Prompts and Output Parsers.ipynb index 934ed7b..bbe2ba7 100644 --- a/content/LangChain for LLM Application Development/2.模型、提示和解析器 Models, Prompts and Output Parsers.ipynb +++ b/content/LangChain for LLM Application Development/2.模型、提示和解析器 Models, Prompts and Output Parsers.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# \u7b2c\u4e8c\u7ae0 \u6a21\u578b\uff0c\u63d0\u793a\u548c\u8f93\u51fa\u89e3\u91ca\u5668\n", "\n", " - [\u4e00\u3001\u8bbe\u7f6eOpenAI API Key](#\u4e00\u3001\u8bbe\u7f6eOpenAI-API-Key)\n", " - [\u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI](#\u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI)\n", " - [2.1 \u8ba1\u7b971+1](#2.1-\u8ba1\u7b971+1)\n", " - [2.2 \u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6](#2.2-\u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6)\n", " - [2.3 \u4e2d\u6587\u7248](#2.3-\u4e2d\u6587\u7248)\n", " - [\u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI](#\u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI)\n", " - [3.1 \u6a21\u578b](#3.1-\u6a21\u578b)\n", " - [3.2 \u63d0\u793a\u6a21\u677f](#3.2-\u63d0\u793a\u6a21\u677f)\n", " - [3.3 \u8f93\u51fa\u89e3\u6790\u5668](#3.3-\u8f93\u51fa\u89e3\u6790\u5668)\n", " - [\u56db\u3001\u8865\u5145\u6750\u6599](#\u56db\u3001\u8865\u5145\u6750\u6599)\n", " - [4.1 \u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct)](#4.1-\u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct))\n"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e00\u3001\u8bbe\u7f6eOpenAI API Key\n", "\n", "\u767b\u9646 [OpenAI \u8d26\u6237](https://platform.openai.com/account/api-keys) \u83b7\u53d6API Key\uff0c\u7136\u540e\u5c06\u5176\u8bbe\u7f6e\u4e3a\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u5168\u5c40\u73af\u5883\u53d8\u91cf\uff0c\u53ef\u4ee5\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://zhuanlan.zhihu.com/p/627665725)\u3002\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u672c\u5730/\u9879\u76ee\u73af\u5883\u53d8\u91cf\uff0c\u5728\u672c\u6587\u4ef6\u76ee\u5f55\u4e0b\u521b\u5efa`.env`\u6587\u4ef6, \u6253\u5f00\u6587\u4ef6\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u3002\n", "\n", "

\n", " OPENAI_API_KEY=\"your_api_key\" \n", "

\n", " \n", " \u66ff\u6362\"your_api_key\"\u4e3a\u4f60\u81ea\u5df1\u7684 API Key"]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": ["# \u4e0b\u8f7d\u9700\u8981\u7684\u5305python-dotenv\u548copenai\n", "# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "!pip install -q python-dotenv\n", "!pip install -q openai"]}, {"cell_type": "code", "execution_count": 2, "metadata": {"tags": []}, "outputs": [], "source": ["import os\n", "import openai\n", "from dotenv import load_dotenv, find_dotenv\n", "\n", "# \u8bfb\u53d6\u672c\u5730/\u9879\u76ee\u7684\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "# find_dotenv()\u5bfb\u627e\u5e76\u5b9a\u4f4d.env\u6587\u4ef6\u7684\u8def\u5f84\n", "# load_dotenv()\u8bfb\u53d6\u8be5.env\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u52a0\u8f7d\u5230\u5f53\u524d\u7684\u8fd0\u884c\u73af\u5883\u4e2d \n", "# \u5982\u679c\u4f60\u8bbe\u7f6e\u7684\u662f\u5168\u5c40\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u884c\u4ee3\u7801\u5219\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n", "_ = load_dotenv(find_dotenv())\n", "\n", "# \u83b7\u53d6\u73af\u5883\u53d8\u91cf OPENAI_API_KEY\n", "openai.api_key = os.environ['OPENAI_API_KEY'] "]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI\n", "\n", "\u6211\u4eec\u5148\u4ece\u76f4\u63a5\u8c03\u7528OpenAI\u7684API\u5f00\u59cb\u3002\n", "\n", "`get_completion`\u51fd\u6570\u662f\u57fa\u4e8e`openai`\u7684\u5c01\u88c5\u51fd\u6570\uff0c\u5bf9\u4e8e\u7ed9\u5b9a\u63d0\u793a\uff08prompt\uff09\u8f93\u51fa\u76f8\u5e94\u7684\u56de\u7b54\u3002\u5176\u5305\u542b\u4e24\u4e2a\u53c2\u6570\n", " \n", " - `prompt` \u5fc5\u9700\u8f93\u5165\u53c2\u6570\u3002 \u4f60\u7ed9\u6a21\u578b\u7684**\u63d0\u793a\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u95ee\u9898\uff0c\u53ef\u4ee5\u662f\u4f60\u9700\u8981\u6a21\u578b\u5e2e\u52a9\u4f60\u505a\u7684\u4e8b**\uff08\u6539\u53d8\u6587\u672c\u5199\u4f5c\u98ce\u683c\uff0c\u7ffb\u8bd1\uff0c\u56de\u590d\u6d88\u606f\u7b49\u7b49\uff09\u3002\n", " - `model` \u975e\u5fc5\u9700\u8f93\u5165\u53c2\u6570\u3002\u9ed8\u8ba4\u4f7f\u7528gpt-3.5-turbo\u3002\u4f60\u4e5f\u53ef\u4ee5\u9009\u62e9\u5176\u4ed6\u6a21\u578b\u3002\n", " \n", "\u8fd9\u91cc\u7684\u63d0\u793a\u5bf9\u5e94\u6211\u4eec\u7ed9chatgpt\u7684\u95ee\u9898\uff0c\u51fd\u6570\u7ed9\u51fa\u7684\u8f93\u51fa\u5219\u5bf9\u5e94chatpgt\u7ed9\u6211\u4eec\u7684\u7b54\u6848\u3002"]}, {"cell_type": "code", "execution_count": 3, "metadata": {"tags": []}, "outputs": [], "source": ["def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", " \n", " messages = [{\"role\": \"user\", \"content\": prompt}]\n", " \n", " response = openai.ChatCompletion.create(\n", " model=model,\n", " messages=messages,\n", " temperature=0, \n", " )\n", " return response.choices[0].message[\"content\"]"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.1 \u8ba1\u7b971+1\n", "\n", "\u6211\u4eec\u6765\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50 - \u5206\u522b\u7528\u4e2d\u82f1\u6587\u95ee\u95ee\u6a21\u578b\n", "\n", "- \u4e2d\u6587\u63d0\u793a(Prompt in Chinese)\uff1a `1+1\u662f\u4ec0\u4e48\uff1f`\n", "- \u82f1\u6587\u63d0\u793a(Prompt in English)\uff1a `What is 1+1?`"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"text/plain": ["'1+1\u7b49\u4e8e2\u3002'"]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "get_completion(\"1+1\u662f\u4ec0\u4e48\uff1f\")"]}, {"cell_type": "code", "execution_count": 5, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["'1+1 equals 2.'"]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u82f1\u6587\n", "get_completion(\"What is 1+1?\")"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.2 \u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6\n", "\n", "\u4e0a\u9762\u7684\u7b80\u5355\u4f8b\u5b50\uff0c\u6a21\u578b`gpt-3.5-turbo`\u5bf9\u6211\u4eec\u7684\u5173\u4e8e1+1\u662f\u4ec0\u4e48\u7684\u63d0\u95ee\u7ed9\u51fa\u4e86\u56de\u7b54\u3002\n", "\n", "\u73b0\u5728\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u590d\u6742\u4e00\u70b9\u7684\u4f8b\u5b50\uff1a \n", "\n", "\u5047\u8bbe\u6211\u4eec\u662f\u7535\u5546\u516c\u53f8\u5458\u5de5\uff0c\u6211\u4eec\u7684\u987e\u5ba2\u662f\u4e00\u540d\u6d77\u76d7A\uff0c\u4ed6\u5728\u6211\u4eec\u7684\u7f51\u7ad9\u4e0a\u4e70\u4e86\u4e00\u4e2a\u69a8\u6c41\u673a\u7528\u6765\u505a\u5976\u6614\uff0c\u5728\u5236\u4f5c\u5976\u6614\u7684\u8fc7\u7a0b\u4e2d\uff0c\u5976\u6614\u7684\u76d6\u5b50\u98de\u4e86\u51fa\u53bb\uff0c\u5f04\u5f97\u53a8\u623f\u5899\u4e0a\u5230\u5904\u90fd\u662f\u3002\u4e8e\u662f\u6d77\u76d7A\u7ed9\u6211\u4eec\u7684\u5ba2\u670d\u4e2d\u5fc3\u5199\u6765\u4ee5\u4e0b\u90ae\u4ef6\uff1a`customer_email`"]}, {"cell_type": "code", "execution_count": 6, "metadata": {"tags": []}, "outputs": [], "source": ["customer_email = \"\"\"\n", "Arrr, I be fuming that me blender lid \\\n", "flew off and splattered me kitchen walls \\\n", "with smoothie! And to make matters worse,\\\n", "the warranty don't cover the cost of \\\n", "cleaning up me kitchen. I need yer help \\\n", "right now, matey!\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u6211\u4eec\u7684\u5ba2\u670d\u4eba\u5458\u5bf9\u4e8e\u6d77\u76d7\u7684\u63aa\u8f9e\u8868\u8fbe\u89c9\u5f97\u6709\u70b9\u96be\u4ee5\u7406\u89e3\u3002 \u73b0\u5728\u6211\u4eec\u60f3\u8981\u5b9e\u73b0\u4e24\u4e2a\u5c0f\u76ee\u6807\uff1a\n", "\n", "- \u8ba9\u6a21\u578b\u7528\u7f8e\u5f0f\u82f1\u8bed\u7684\u8868\u8fbe\u65b9\u5f0f\u5c06\u6d77\u76d7\u7684\u90ae\u4ef6\u8fdb\u884c\u7ffb\u8bd1\uff0c\u5ba2\u670d\u4eba\u5458\u53ef\u4ee5\u66f4\u597d\u7406\u89e3\u3002*\u8fd9\u91cc\u6d77\u76d7\u7684\u82f1\u6587\u8868\u8fbe\u53ef\u4ee5\u7406\u89e3\u4e3a\u82f1\u6587\u7684\u65b9\u8a00\uff0c\u5176\u4e0e\u7f8e\u5f0f\u82f1\u8bed\u7684\u5173\u7cfb\uff0c\u5c31\u5982\u56db\u5ddd\u8bdd\u4e0e\u666e\u901a\u8bdd\u7684\u5173\u7cfb\u3002\n", "- \u8ba9\u6a21\u578b\u5728\u7ffb\u8bd1\u662f\u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\u8fdb\u884c\u8868\u8fbe\uff0c\u5ba2\u670d\u4eba\u5458\u7684\u5fc3\u60c5\u4e5f\u4f1a\u66f4\u597d\u3002\n", "\n", "\u6839\u636e\u8fd9\u4e24\u4e2a\u5c0f\u76ee\u6807\uff0c\u5b9a\u4e49\u4e00\u4e0b\u6587\u672c\u8868\u8fbe\u98ce\u683c\uff1a`style`"]}, {"cell_type": "code", "execution_count": 7, "metadata": {"tags": []}, "outputs": [], "source": ["# \u7f8e\u5f0f\u82f1\u8bed + \u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "style = \"\"\"American English \\\n", "in a calm and respectful tone\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0b\u4e00\u6b65\u9700\u8981\u505a\u7684\u662f\u5c06`customer_email`\u548c`style`\u7ed3\u5408\u8d77\u6765\u6784\u9020\u6211\u4eec\u7684\u63d0\u793a:`prompt`"]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": ["# \u975e\u6b63\u5f0f\u7528\u8bed\n", "customer_email = \"\"\" \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\\\n", "\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\\\n", "\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\\\n", "\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\\\n", "\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 9, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Translate the text that is delimited by triple backticks \n", "into a style that is American English in a calm and respectful tone\n", ".\n", "text: ``` \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "```\n", "\n"]}], "source": ["# \u8981\u6c42\u6a21\u578b\u6839\u636e\u7ed9\u51fa\u7684\u8bed\u8c03\u8fdb\u884c\u8f6c\u5316\n", "prompt = f\"\"\"Translate the text \\\n", "that is delimited by triple backticks \n", "into a style that is {style}.\n", "text: ```{customer_email}```\n", "\"\"\"\n", "\n", "print(prompt)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["`prompt` \u6784\u9020\u597d\u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u8c03\u7528`get_completion`\u5f97\u5230\u6211\u4eec\u60f3\u8981\u7684\u7ed3\u679c - \u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\uff0c\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u7684\u6d77\u76d7\u8bed\u8a00\u90ae\u4ef6"]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": ["response = get_completion(prompt)"]}, {"cell_type": "code", "execution_count": 11, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["\"Oh, I'm really frustrated because the lid of my blender fell off and splattered the milkshake all over the kitchen wall! To make matters worse, the warranty doesn't cover the cost of cleaning the kitchen. I could really use your help right now, buddy!\""]}, "execution_count": 11, "metadata": {}, "output_type": "execute_result"}], "source": ["response"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5bf9\u6bd4\u8bed\u8a00\u98ce\u683c\u8f6c\u6362\u524d\u540e\uff0c\u7528\u8bcd\u66f4\u4e3a\u6b63\u5f0f\uff0c\u66ff\u6362\u4e86\u6781\u7aef\u60c5\u7eea\u7684\u8868\u8fbe\uff0c\u5e76\u8868\u8fbe\u4e86\u611f\u8c22\u3002\n", "\n", "\u2728 \u4f60\u53ef\u4ee5\u5c1d\u8bd5\u4fee\u6539\u63d0\u793a\uff0c\u770b\u53ef\u4ee5\u5f97\u5230\u4ec0\u4e48\u4e0d\u4e00\u6837\u7684\u7ed3\u679c\ud83d\ude09"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.3 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": ["# \u666e\u901a\u8bdd + \u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "style = \"\"\"\u6b63\u5f0f\u666e\u901a\u8bdd \\\n", "\u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u6b63\u5f0f\u666e\u901a\u8bdd \u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "\u98ce\u683c\u3002\n", "\u6587\u672c: ``` \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "```\n", "\n"]}], "source": ["# \u8981\u6c42\u6a21\u578b\u6839\u636e\u7ed9\u51fa\u7684\u8bed\u8c03\u8fdb\u884c\u8f6c\u5316\n", "prompt = f\"\"\"\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\\\n", "\u7ffb\u8bd1\u6210\u4e00\u79cd{style}\u98ce\u683c\u3002\n", "\u6587\u672c: ```{customer_email}```\n", "\"\"\"\n", "\n", "print(prompt)\n", "\n"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["'\u5c0a\u656c\u7684\u670b\u53cb\u4eec\uff0c\u6211\u611f\u5230\u975e\u5e38\u4e0d\u5b89\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u670d\u52a1\u5e76\u4e0d\u5305\u542b\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u6b64\u523b\uff0c\u6211\u771f\u8bda\u5730\u8bf7\u6c42\u5404\u4f4d\u7684\u5e2e\u52a9\uff0c\u670b\u53cb\u4eec\uff01'"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["response = get_completion(prompt)\n", "\n", "response"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI\n", "\n", "\u5728\u524d\u9762\u4e00\u90e8\u5206\uff0c\u6211\u4eec\u901a\u8fc7\u5c01\u88c5\u51fd\u6570`get_completion`\u76f4\u63a5\u8c03\u7528\u4e86OpenAI\u5b8c\u6210\u4e86\u5bf9\u65b9\u8a00\u90ae\u4ef6\u8fdb\u884c\u4e86\u7684\u7ffb\u8bd1\uff0c\u5f97\u5230\u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\u3001\u6b63\u5f0f\u7684\u666e\u901a\u8bdd\u8868\u8fbe\u7684\u90ae\u4ef6\u3002\n", "\n", "\u8ba9\u6211\u4eec\u5c1d\u8bd5\u4f7f\u7528LangChain\u6765\u5b9e\u73b0\u76f8\u540c\u7684\u529f\u80fd\u3002"]}, {"cell_type": "code", "execution_count": 15, "metadata": {"tags": []}, "outputs": [], "source": ["# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "# --upgrade \u8ba9\u6211\u4eec\u53ef\u4ee5\u5b89\u88c5\u5230\u6700\u65b0\u7248\u672c\u7684 langchain\n", "!pip install -q --upgrade langchain"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 3.1 \u6a21\u578b\n", "\n", "\u4ece`langchain.chat_models`\u5bfc\u5165`OpenAI`\u7684\u5bf9\u8bdd\u6a21\u578b`ChatOpenAI`\u3002 \u9664\u53bbOpenAI\u4ee5\u5916\uff0c`langchain.chat_models`\u8fd8\u96c6\u6210\u4e86\u5176\u4ed6\u5bf9\u8bdd\u6a21\u578b\uff0c\u66f4\u591a\u7ec6\u8282\u53ef\u4ee5\u67e5\u770b[Langchain\u5b98\u65b9\u6587\u6863](https://python.langchain.com/en/latest/modules/models/chat/integrations.html)\u3002"]}, {"cell_type": "code", "execution_count": 16, "metadata": {"tags": []}, "outputs": [], "source": ["from langchain.chat_models import ChatOpenAI"]}, {"cell_type": "code", "execution_count": 17, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, client=, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None)"]}, "execution_count": 17, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u8fd9\u91cc\u6211\u4eec\u5c06\u53c2\u6570temperature\u8bbe\u7f6e\u4e3a0.0\uff0c\u4ece\u800c\u51cf\u5c11\u751f\u6210\u7b54\u6848\u7684\u968f\u673a\u6027\u3002\n", "# \u5982\u679c\u4f60\u60f3\u8981\u6bcf\u6b21\u5f97\u5230\u4e0d\u4e00\u6837\u7684\u6709\u65b0\u610f\u7684\u7b54\u6848\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u8c03\u6574\u8be5\u53c2\u6570\u3002\n", "chat = ChatOpenAI(temperature=0.0)\n", "chat"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0a\u9762\u7684\u8f93\u51fa\u663e\u793aChatOpenAI\u7684\u9ed8\u8ba4\u6a21\u578b\u4e3a`gpt-3.5-turbo`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 3.2 \u63d0\u793a\u6a21\u677f\n", "\n", "\u5728\u524d\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u901a\u8fc7[f\u5b57\u7b26\u4e32](https://docs.python.org/zh-cn/3/tutorial/inputoutput.html#tut-f-strings)\u628aPython\u8868\u8fbe\u5f0f\u7684\u503c`style`\u548c`customer_email`\u6dfb\u52a0\u5230`prompt`\u5b57\u7b26\u4e32\u5185\u3002\n", "\n", "```python\n", "prompt = f\"\"\"Translate the text \\\n", "that is delimited by triple backticks \n", "into a style that is {style}.\n", "text: ```{customer_email}```\n", "\"\"\"\n", "```\n", "`langchain`\u63d0\u4f9b\u4e86\u63a5\u53e3\u65b9\u4fbf\u5feb\u901f\u7684\u6784\u9020\u548c\u4f7f\u7528\u63d0\u793a\u3002\u73b0\u5728\u6211\u4eec\u6765\u770b\u770b\u5982\u4f55\u4f7f\u7528`langchain`\u6765\u6784\u9020\u63d0\u793a\u3002"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["#### 3.2.1 \u4f7f\u7528LangChain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32\n", "\u6211\u4eec\u6784\u9020\u4e00\u4e2a\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32\uff1a`template_string`"]}, {"cell_type": "code", "execution_count": 18, "metadata": {"tags": []}, "outputs": [], "source": ["template_string = \"\"\"Translate the text \\\n", "that is delimited by triple backticks \\\n", "into a style that is {style}. \\\n", "text: ```{text}```\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020LangChain\u63d0\u793a\u6a21\u7248\n", "\u6211\u4eec\u8c03\u7528`ChatPromptTemplatee.from_template()`\u51fd\u6570\u5c06\u4e0a\u9762\u7684\u63d0\u793a\u6a21\u7248\u5b57\u7b26`template_string`\u8f6c\u6362\u4e3a\u63d0\u793a\u6a21\u7248`prompt_template`"]}, {"cell_type": "code", "execution_count": 19, "metadata": {"tags": []}, "outputs": [], "source": ["from langchain.prompts import ChatPromptTemplate\n", "prompt_template = ChatPromptTemplate.from_template(template_string)"]}, {"cell_type": "code", "execution_count": 20, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['style', 'text'] output_parser=None partial_variables={} template='Translate the text that is delimited by triple backticks into a style that is {style}. text: ```{text}```\\n' template_format='f-string' validate_template=True\n"]}], "source": ["print(prompt_template.messages[0].prompt)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4ece\u4e0a\u9762\u7684\u8f93\u51fa\u53ef\u4ee5\u770b\u51fa\uff0c`prompt_template` \u6709\u4e24\u4e2a\u8f93\u5165\u53d8\u91cf\uff1a `style` \u548c `text`\u3002"]}, {"cell_type": "code", "execution_count": 21, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["['style', 'text']\n"]}], "source": ["print(prompt_template.messages[0].prompt.input_variables)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u5ba2\u6237\u6d88\u606f\u63d0\u793a\n", "\n", "langchain\u63d0\u793a\u6a21\u7248`prompt_template`\u9700\u8981\u4e24\u4e2a\u8f93\u5165\u53d8\u91cf\uff1a `style` \u548c `text`\u3002 \u8fd9\u91cc\u5206\u522b\u5bf9\u5e94 \n", "- `customer_style`: \u6211\u4eec\u60f3\u8981\u7684\u987e\u5ba2\u90ae\u4ef6\u98ce\u683c\n", "- `customer_email`: \u987e\u5ba2\u7684\u539f\u59cb\u90ae\u4ef6\u6587\u672c\u3002"]}, {"cell_type": "code", "execution_count": 22, "metadata": {"tags": []}, "outputs": [], "source": ["customer_style = \"\"\"American English \\\n", "in a calm and respectful tone\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 23, "metadata": {"tags": []}, "outputs": [], "source": ["customer_email = \"\"\"\n", "Arrr, I be fuming that me blender lid \\\n", "flew off and splattered me kitchen walls \\\n", "with smoothie! And to make matters worse, \\\n", "the warranty don't cover the cost of \\\n", "cleaning up me kitchen. I need yer help \\\n", "right now, matey!\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5bf9\u4e8e\u7ed9\u5b9a\u7684`customer_style`\u548c`customer_email`, \u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u63d0\u793a\u6a21\u7248`prompt_template`\u7684`format_messages`\u65b9\u6cd5\u751f\u6210\u60f3\u8981\u7684\u5ba2\u6237\u6d88\u606f`customer_messages`\u3002"]}, {"cell_type": "code", "execution_count": 24, "metadata": {"tags": []}, "outputs": [], "source": ["customer_messages = prompt_template.format_messages(\n", " style=customer_style,\n", " text=customer_email)"]}, {"cell_type": "code", "execution_count": 25, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n"]}], "source": ["print(type(customer_messages))\n", "print(type(customer_messages[0]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u53ef\u4ee5\u770b\u51fa`customer_messages`\u53d8\u91cf\u7c7b\u578b\u4e3a\u5217\u8868(`list`)\uff0c\u800c\u5217\u8868\u91cc\u7684\u5143\u7d20\u53d8\u91cf\u7c7b\u578b\u4e3alangchain\u81ea\u5b9a\u4e49\u6d88\u606f(`langchain.schema.HumanMessage`)\u3002\n", "\n", "\u6253\u5370\u7b2c\u4e00\u4e2a\u5143\u7d20\u53ef\u4ee5\u5f97\u5230\u5982\u4e0b:"]}, {"cell_type": "code", "execution_count": 26, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["content=\"Translate the text that is delimited by triple backticks into a style that is American English in a calm and respectful tone\\n. text: ```\\nArrr, I be fuming that me blender lid flew off and splattered me kitchen walls with smoothie! And to make matters worse, the warranty don't cover the cost of cleaning up me kitchen. I need yer help right now, matey!\\n```\\n\" additional_kwargs={} example=False\n"]}], "source": ["print(customer_messages[0])"]}, {"cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["content='\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u6b63\u5f0f\u666e\u901a\u8bdd \u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u6c14\\n\u98ce\u683c\u3002\u6587\u672c: ```\\n\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\\n```\\n' additional_kwargs={} example=False\n"]}], "source": ["# \u4e2d\u6587\u63d0\u793a\n", "from langchain.prompts import ChatPromptTemplate\n", "\n", "template_string = \"\"\"\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\\\n", "\u7ffb\u8bd1\u6210\u4e00\u79cd{style}\u98ce\u683c\u3002\\\n", "\u6587\u672c: ```{text}```\n", "\"\"\"\n", "prompt_template = ChatPromptTemplate.from_template(template_string)\n", "\n", "customer_style = \"\"\"\u6b63\u5f0f\u666e\u901a\u8bdd \\\n", "\u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u6c14\n", "\"\"\"\n", "\n", "customer_email = \"\"\"\n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\\\n", "\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\\\n", "\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\\\n", "\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\\\n", "\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "\"\"\"\n", "\n", "customer_messages = prompt_template.format_messages(\n", " style=customer_style,\n", " text=customer_email)\n", "\n", "\n", "print(customer_messages[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u8f6c\u6362\u5ba2\u6237\u6d88\u606f\u98ce\u683c\n", "\n", "\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u8c03\u7528[\u6a21\u578b](#model)\u90e8\u5206\u5b9a\u4e49\u7684chat\u6a21\u578b\u6765\u5b9e\u73b0\u8f6c\u6362\u5ba2\u6237\u6d88\u606f\u98ce\u683c\u3002\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5df2\u7ecf\u5b9e\u73b0\u4e86\u5728\u524d\u4e00\u90e8\u5206\u7684\u4efb\u52a1\u3002"]}, {"cell_type": "code", "execution_count": 28, "metadata": {"tags": []}, "outputs": [], "source": ["customer_response = chat(customer_messages)"]}, {"cell_type": "code", "execution_count": 29, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u4f19\u8ba1\uff0c\u6211\u611f\u5230\u975e\u5e38\u6124\u6012\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u5e76\u4e0d\u5305\u62ec\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u73b0\u5728\uff0c\u6211\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u8bf7\u4f60\u7ed9\u4e88\u63f4\u624b\uff01\n"]}], "source": ["print(customer_response.content)"]}, {"cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u4f19\u8ba1\uff0c\u6211\u611f\u5230\u975e\u5e38\u6124\u6012\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u5e76\u4e0d\u5305\u62ec\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u73b0\u5728\uff0c\u6211\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u8bf7\u4f60\u7ed9\u4e88\u63f4\u624b\uff01\n"]}], "source": ["print(customer_response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 5\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u56de\u590d\u6d88\u606f\u63d0\u793a\n", "\n", "\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u66f4\u8fdb\u4e00\u6b65\uff0c\u5c06\u5ba2\u670d\u4eba\u5458\u56de\u590d\u7684\u6d88\u606f\uff0c\u8f6c\u6362\u4e3a\u6d77\u76d7\u7684\u8bed\u8a00\u98ce\u683c\uff0c\u5e76\u786e\u4fdd\u6d88\u606f\u6bd4\u8f83\u6709\u793c\u8c8c\u3002 \n", "\n", "\u8fd9\u91cc\uff0c\u6211\u4eec\u53ef\u4ee5\u7ee7\u7eed\u4f7f\u7528\u7b2c2\ufe0f\u20e3\u6b65\u6784\u9020\u7684langchain\u63d0\u793a\u6a21\u7248\uff0c\u6765\u83b7\u5f97\u6211\u4eec\u56de\u590d\u6d88\u606f\u63d0\u793a\u3002"]}, {"cell_type": "code", "execution_count": 31, "metadata": {"tags": []}, "outputs": [], "source": ["service_reply = \"\"\"Hey there customer, \\\n", "the warranty does not cover \\\n", "cleaning expenses for your kitchen \\\n", "because it's your fault that \\\n", "you misused your blender \\\n", "by forgetting to put the lid on before \\\n", "starting the blender. \\\n", "Tough luck! See ya!\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": ["service_style_pirate = \"\"\"\\\n", "a polite tone \\\n", "that speaks in English Pirate\\\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 33, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cda polite tone that speaks in English Pirate\u98ce\u683c\u3002\u6587\u672c: ```Hey there customer, the warranty does not cover cleaning expenses for your kitchen because it's your fault that you misused your blender by forgetting to put the lid on before starting the blender. Tough luck! See ya!\n", "```\n", "\n"]}], "source": ["service_messages = prompt_template.format_messages(\n", " style=service_style_pirate,\n", " text=service_reply)\n", "\n", "print(service_messages[0].content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 6\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u8f6c\u6362\u56de\u590d\u6d88\u606f\u98ce\u683c\n", "\n", "\u8c03\u7528[\u6a21\u578b](#model)\u90e8\u5206\u5b9a\u4e49\u7684chat\u6a21\u578b\u6765\u8f6c\u6362\u56de\u590d\u6d88\u606f\u98ce\u683c"]}, {"cell_type": "code", "execution_count": 34, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Ahoy there, matey! I regret to inform ye, valued customer, that the warranty be not coverin' the expenses o' cleanin' yer galley due to yer own negligence. 'Tis yer own fault, ye see, fer ye be misusin' yer blender by forgettin' to secure the lid afore settin' it in motion. Aye, 'tis a tough break, indeed! Fare thee well, me heartie!\n"]}], "source": ["service_response = chat(service_messages)\n", "print(service_response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.2.2 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u4e00\u4e2a\u6709\u793c\u8c8c\u7684\u8bed\u6c14 \u4f7f\u7528\u6b63\u5f0f\u7684\u666e\u901a\u8bdd \u98ce\u683c\u3002\u6587\u672c: ```\u563f\uff0c\u987e\u5ba2\uff0c \u4fdd\u4fee\u4e0d\u5305\u62ec\u53a8\u623f\u7684\u6e05\u6d01\u8d39\u7528\uff0c \u56e0\u4e3a\u60a8\u5728\u542f\u52a8\u6405\u62cc\u673a\u4e4b\u524d \u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u8bef\u7528\u6405\u62cc\u673a, \u8fd9\u662f\u60a8\u7684\u9519\u3002 \u5012\u9709\uff01 \u518d\u89c1\uff01\n", "```\n", "\n"]}], "source": ["service_reply = \"\"\"\u563f\uff0c\u987e\u5ba2\uff0c \\\n", "\u4fdd\u4fee\u4e0d\u5305\u62ec\u53a8\u623f\u7684\u6e05\u6d01\u8d39\u7528\uff0c \\\n", "\u56e0\u4e3a\u60a8\u5728\u542f\u52a8\u6405\u62cc\u673a\u4e4b\u524d \\\n", "\u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u8bef\u7528\u6405\u62cc\u673a, \\\n", "\u8fd9\u662f\u60a8\u7684\u9519\u3002 \\\n", "\u5012\u9709\uff01 \u518d\u89c1\uff01\n", "\"\"\"\n", "\n", "service_style_pirate = \"\"\"\\\n", "\u4e00\u4e2a\u6709\u793c\u8c8c\u7684\u8bed\u6c14 \\\n", "\u4f7f\u7528\u6b63\u5f0f\u7684\u666e\u901a\u8bdd \\\n", "\"\"\"\n", "service_messages = prompt_template.format_messages(\n", " style=service_style_pirate,\n", " text=service_reply)\n", "\n", "print(service_messages[0].content)"]}, {"cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u987e\u5ba2\uff0c\u5f88\u62b1\u6b49\u544a\u77e5\u60a8\uff0c\u4fdd\u4fee\u670d\u52a1\u4e0d\u5305\u542b\u53a8\u623f\u6e05\u6d01\u8d39\u7528\u3002\u8fd9\u662f\u56e0\u4e3a\u5728\u60a8\u4f7f\u7528\u6405\u62cc\u673a\u4e4b\u524d\uff0c\u4e0d\u614e\u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u5bfc\u81f4\u8bef\u7528\u6405\u62cc\u673a\uff0c\u8fd9\u5c5e\u4e8e\u60a8\u7684\u758f\u5ffd\u3002\u975e\u5e38\u9057\u61be\uff01\u795d\u60a8\u4e00\u5207\u987a\u5229\uff01\u518d\u89c1\uff01\n"]}], "source": ["service_response = chat(service_messages)\n", "print(service_response.content)"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["#### 3.2.2 \u4e3a\u4ec0\u4e48\u9700\u8981\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5728\u5e94\u7528\u4e8e\u6bd4\u8f83\u590d\u6742\u7684\u573a\u666f\u65f6\uff0c\u63d0\u793a\u53ef\u80fd\u4f1a\u975e\u5e38\u957f\u5e76\u4e14\u5305\u542b\u6d89\u53ca\u8bb8\u591a\u7ec6\u8282\u3002**\u4f7f\u7528\u63d0\u793a\u6a21\u7248\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u66f4\u4e3a\u65b9\u4fbf\u5730\u91cd\u590d\u4f7f\u7528\u8bbe\u8ba1\u597d\u7684\u63d0\u793a**\u3002"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0b\u9762\u7ed9\u51fa\u4e86\u4e00\u4e2a\u6bd4\u8f83\u957f\u7684\u63d0\u793a\u6a21\u7248\u6848\u4f8b\u3002\u5b66\u751f\u4eec\u7ebf\u4e0a\u5b66\u4e60\u5e76\u63d0\u4ea4\u4f5c\u4e1a\uff0c\u901a\u8fc7\u4ee5\u4e0b\u7684\u63d0\u793a\u6765\u5b9e\u73b0\u5bf9\u5b66\u751f\u7684\u63d0\u4ea4\u7684\u4f5c\u4e1a\u7684\u8bc4\u5206\u3002"]}, {"cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": ["# \u82f1\u6587\u7248\n", "prompt = \"\"\" Your task is to determine if the student's solution is correct or not\n", "\n", " To solve the problem do the following:\n", " - First, workout your own solution to the problem\n", " - Then compare your solution to the student's solution \n", " and evaluate if the sudtent's solution is correct or not.\n", " ...\n", " Use the following format:\n", " Question:\n", " ```\n", " question here\n", " ```\n", " Student's solution:\n", " ```\n", " student's solution here\n", " ```\n", " Actual solution:\n", " ```\n", " ...\n", " steps to work out the solution and your solution here\n", " ```\n", " Is the student's solution the same as acutal solution \\\n", " just calculated:\n", " ```\n", " yes or no\n", " ```\n", " Student grade\n", " ```\n", " correct or incorrect\n", " ```\n", " \n", " Question:\n", " ```\n", " {question}\n", " ```\n", " Student's solution:\n", " ```\n", " {student's solution}\n", " ```\n", " Actual solution:\n", " \n", " \"\"\""]}, {"cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\u7248\n", "prompt = \"\"\" \u4f60\u7684\u4efb\u52a1\u662f\u5224\u65ad\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u662f\u6b63\u786e\u7684\u8fd8\u662f\u4e0d\u6b63\u786e\u7684\n", "\n", "\u8981\u89e3\u51b3\u8be5\u95ee\u9898\uff0c\u8bf7\u6267\u884c\u4ee5\u4e0b\u64cd\u4f5c\uff1a\n", " - \u9996\u5148\uff0c\u5236\u5b9a\u81ea\u5df1\u7684\u95ee\u9898\u89e3\u51b3\u65b9\u6848\n", " - \u7136\u540e\u5c06\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u4e0e\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u8fdb\u884c\u6bd4\u8f83\n", " \u5e76\u8bc4\u4f30\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u662f\u5426\u6b63\u786e\u3002\n", "...\n", "\u4f7f\u7528\u4e0b\u9762\u7684\u683c\u5f0f:\n", "\n", "\u95ee\u9898:\n", "```\n", "\u95ee\u9898\u6587\u672c\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848:\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u6587\u672c\n", "```\n", "\u5b9e\u9645\u89e3\u51b3\u65b9\u6848:\n", "```\n", "...\n", "\u5236\u5b9a\u89e3\u51b3\u65b9\u6848\u7684\u6b65\u9aa4\u4ee5\u53ca\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u8bf7\u53c2\u89c1\u6b64\u5904\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u548c\u5b9e\u9645\u89e3\u51b3\u65b9\u6848\u662f\u5426\u76f8\u540c \\\n", "\u53ea\u8ba1\u7b97\uff1a\n", "```\n", "\u662f\u6216\u8005\u4e0d\u662f\n", "```\n", "\u5b66\u751f\u7684\u6210\u7ee9\n", "```\n", "\u6b63\u786e\u6216\u8005\u4e0d\u6b63\u786e\n", "```\n", "\n", "\u95ee\u9898:\n", "```\n", "{question}\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848:\n", "```\n", "{student's solution}\n", "```\n", "\u5b9e\u9645\u89e3\u51b3\u65b9\u6848:\n", "\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {"jp-MarkdownHeadingCollapsed": true, "tags": []}, "source": ["\u6b64\u5916\uff0cLangChain\u8fd8\u63d0\u4f9b\u4e86\u63d0\u793a\u6a21\u7248\u7528\u4e8e\u4e00\u4e9b\u5e38\u7528\u573a\u666f\u3002\u6bd4\u5982\u81ea\u52a8\u6458\u8981\u3001\u95ee\u7b54\u3001\u8fde\u63a5\u5230SQL\u6570\u636e\u5e93\u3001\u8fde\u63a5\u5230\u4e0d\u540c\u7684API. \u901a\u8fc7\u4f7f\u7528LongChain\u5185\u7f6e\u7684\u63d0\u793a\u6a21\u7248\uff0c\u4f60\u53ef\u4ee5\u5feb\u901f\u5efa\u7acb\u81ea\u5df1\u7684\u5927\u6a21\u578b\u5e94\u7528\uff0c\u800c\u4e0d\u9700\u8981\u82b1\u65f6\u95f4\u53bb\u8bbe\u8ba1\u548c\u6784\u9020\u63d0\u793a\u3002\n", "\n", "\u6700\u540e\uff0c\u6211\u4eec\u5728\u5efa\u7acb\u5927\u6a21\u578b\u5e94\u7528\u65f6\uff0c\u901a\u5e38\u5e0c\u671b\u6a21\u578b\u7684\u8f93\u51fa\u4e3a\u7ed9\u5b9a\u7684\u683c\u5f0f\uff0c\u6bd4\u5982\u5728\u8f93\u51fa\u4f7f\u7528\u7279\u5b9a\u7684\u5173\u952e\u8bcd\u6765\u8ba9\u8f93\u51fa\u7ed3\u6784\u5316\u3002 \u4e0b\u9762\u4e3a\u4e00\u4e2a\u4f7f\u7528\u5927\u6a21\u578b\u8fdb\u884c\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u4f8b\u5b50\uff0c\u5bf9\u4e8e\u95ee\u9898\uff1a*What is the elevation range for the area that the eastern sector of the Colorado orogeny extends into?*\n", "\n", "\u901a\u8fc7\u4f7f\u7528LangChain\u5e93\u51fd\u6570\uff0c\u8f93\u51fa\u91c7\u7528\"Thought\"\uff08\u601d\u8003\uff09\u3001\"Action\"\uff08\u884c\u52a8\uff09\u3001\"Observation\"\uff08\u89c2\u5bdf\uff09\u4f5c\u4e3a\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u7684\u5173\u952e\u8bcd\uff0c\u8ba9\u8f93\u51fa\u7ed3\u6784\u5316\u3002\n", "\n", "```\n", "Thought: I need to search Colorado orogeny, find the area that the eastern sector of the Colorado orogeny extends into, then find the elevation range of the area.\n", "Action: Search[Colorado orogeny]\n", "Observation: The Colorado orogeny was an episode of mountain building (an orogeny) in Colorado and surrounding areas.\n", "\n", "Thought: It does not mention the eastern sector. So I need to look up eastern sector.\n", "Action: Lookup[eastern sector]\n", "Observation: (Result 1 / 1) The eastern sector extends into the High Plains and is called the Central Plains orogeny.\n", "\n", "Thought: The eastern sector of Colorado orogeny extends into the High Plains. So I need to search High Plains and find its elevation range.\n", "Action: Search[High Plains]\n", "Observation: High Plains refers to one of two distinct land regions\n", "\n", "Thought: I need to instead search High Plains (United States).\n", "Action: Search[High Plains (United States)]\n", "Observation: The High Plains are a subregion of the Great Plains. From east to west, the High Plains rise in elevation from around 1,800 to 7,000 ft (550 to 2,130 m).[3]\n", "\n", "Thought: High Plains rise in elevation from around 1,800 to 7,000 ft, so the answer is 1,800 to 7,000 ft.\n", "Action: Finish[1,800 to 7,000 ft]\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5728\u8865\u5145\u6750\u6599\u4e2d\uff0c\u53ef\u4ee5\u67e5\u770b\u4f7f\u7528LangChain\u548cOpenAI\u8fdb\u884c\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u7684\u53e6\u4e00\u4e2a\u4ee3\u7801\u5b9e\u4f8b\u3002"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 3.3 \u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.1 \u5982\u679c\u6ca1\u6709\u8f93\u51fa\u89e3\u6790\u5668\n", "\n", "\u5bf9\u4e8e\u7ed9\u5b9a\u7684\u8bc4\u4ef7`customer_review`, \u6211\u4eec\u5e0c\u671b\u63d0\u53d6\u4fe1\u606f\uff0c\u5e76\u6309\u4ee5\u4e0b\u683c\u5f0f\u8f93\u51fa\uff1a\n", "\n", "```python\n", "{\n", " \"gift\": False,\n", " \"delivery_days\": 5,\n", " \"price_value\": \"pretty affordable!\"\n", "}\n", "```"]}, {"cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": ["customer_review = \"\"\"\\\n", "This leaf blower is pretty amazing. It has four settings:\\\n", "candle blower, gentle breeze, windy city, and tornado. \\\n", "It arrived in two days, just in time for my wife's \\\n", "anniversary present. \\\n", "I think my wife liked it so much she was speechless. \\\n", "So far I've been the only one using it, and I've been \\\n", "using it every other morning to clear the leaves on our lawn. \\\n", "It's slightly more expensive than the other leaf blowers \\\n", "out there, but I think it's worth it for the extra features.\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32"]}, {"cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": ["review_template = \"\"\"\\\n", "For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? \\\n", "Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the product \\\n", "to arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,\\\n", "and output them as a comma separated Python list.\n", "\n", "Format the output as JSON with the following keys:\n", "gift\n", "delivery_days\n", "price_value\n", "\n", "text: {text}\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020langchain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['text'] output_parser=None partial_variables={} messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], output_parser=None, partial_variables={}, template='For the following text, extract the following information:\\n\\ngift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\\n\\ndelivery_days: How many days did it take for the product to arrive? If this information is not found, output -1.\\n\\nprice_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\\n\\nFormat the output as JSON with the following keys:\\ngift\\ndelivery_days\\nprice_value\\n\\ntext: {text}\\n', template_format='f-string', validate_template=True), additional_kwargs={})]\n"]}], "source": ["from langchain.prompts import ChatPromptTemplate\n", "prompt_template = ChatPromptTemplate.from_template(review_template)\n", "print(prompt_template)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u63d0\u793a\u6d88\u606f"]}, {"cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": ["messages = prompt_template.format_messages(text=customer_review)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u63d0\u53d6\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{\n", " \"gift\": false,\n", " \"delivery_days\": 2,\n", " \"price_value\": [\"It's slightly more expensive than the other leaf blowers out there, but I think it's worth it for the extra features.\"]\n", "}\n"]}], "source": ["chat = ChatOpenAI(temperature=0.0)\n", "response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udcdd \u5206\u6790\u4e0e\u603b\u7ed3\n", "`response.content`\u7c7b\u578b\u4e3a\u5b57\u7b26\u4e32\uff08`str`\uff09\uff0c\u800c\u5e76\u975e\u5b57\u5178(`dict`), \u76f4\u63a5\u4f7f\u7528`get`\u65b9\u6cd5\u4f1a\u62a5\u9519\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u9700\u8981\u8f93\u51fa\u89e3\u91ca\u5668\u3002"]}, {"cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [{"data": {"text/plain": ["str"]}, "execution_count": 44, "metadata": {}, "output_type": "execute_result"}], "source": ["type(response.content)"]}, {"cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [{"ename": "AttributeError", "evalue": "'str' object has no attribute 'get'", "output_type": "error", "traceback": ["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "Input \u001b[0;32mIn [45]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcontent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgift\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mAttributeError\u001b[0m: 'str' object has no attribute 'get'"]}], "source": ["response.content.get('gift')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.2 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['text'] output_parser=None partial_variables={} messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], output_parser=None, partial_variables={}, template='\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\\n\\n\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\\n\\n\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\\n\\n\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\\n\\n\u4f7f\u7528\u4ee5\u4e0b\u952e\u5c06\u8f93\u51fa\u683c\u5f0f\u5316\u4e3a JSON\uff1a\\n\u793c\u7269\\n\u4ea4\u8d27\u5929\u6570\\n\u4ef7\u94b1\\n\\n\u6587\u672c: {text}\\n', template_format='f-string', validate_template=True), additional_kwargs={})]\n"]}], "source": ["from langchain.prompts import ChatPromptTemplate\n", "\n", "customer_review = \"\"\"\\\n", "\u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\\\n", "\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \\\n", "\u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\\\n", "\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \\\n", "\u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \\\n", "\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\\\n", "\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \\\n", "\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\\\n", "\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\"\"\"\n", "\n", "review_template = \"\"\"\\\n", "\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\n", "\n", "\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \\\n", "\u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\n", "\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\\\n", "\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\n", "\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\\\n", "\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\n", "\n", "\u4f7f\u7528\u4ee5\u4e0b\u952e\u5c06\u8f93\u51fa\u683c\u5f0f\u5316\u4e3a JSON\uff1a\n", "\u793c\u7269\n", "\u4ea4\u8d27\u5929\u6570\n", "\u4ef7\u94b1\n", "\n", "\u6587\u672c: {text}\n", "\"\"\"\n", "\n", "prompt_template = ChatPromptTemplate.from_template(review_template)\n", "print(prompt_template)\n"]}, {"cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{\n", " \"\u793c\u7269\": \"\u662f\u7684\",\n", " \"\u4ea4\u8d27\u5929\u6570\": 2,\n", " \"\u4ef7\u94b1\": [\"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"]\n", "}\n"]}], "source": ["messages = prompt_template.format_messages(text=customer_review)\n", "\n", "chat = ChatOpenAI(temperature=0.0)\n", "response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.3 LangChain\u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32"]}, {"cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": ["review_template_2 = \"\"\"\\\n", "For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? \\\n", "Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the product\\\n", "to arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,\\\n", "and output them as a comma separated Python list.\n", "\n", "text: {text}\n", "\n", "{format_instructions}\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020langchain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": ["prompt = ChatPromptTemplate.from_template(template=review_template_2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udd25 \u6784\u9020\u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"gift\": string // Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\t\"delivery_days\": string // How many days did it take for the product to arrive? If this information is not found, output -1.\n", "\t\"price_value\": string // Extract any sentences about the value or price, and output them as a comma separated Python list.\n", "}\n", "```\n"]}], "source": ["from langchain.output_parsers import ResponseSchema\n", "from langchain.output_parsers import StructuredOutputParser\n", "\n", "gift_schema = ResponseSchema(name=\"gift\",\n", " description=\"Was the item purchased\\\n", " as a gift for someone else? \\\n", " Answer True if yes,\\\n", " False if not or unknown.\")\n", "\n", "delivery_days_schema = ResponseSchema(name=\"delivery_days\",\n", " description=\"How many days\\\n", " did it take for the product\\\n", " to arrive? If this \\\n", " information is not found,\\\n", " output -1.\")\n", "\n", "price_value_schema = ResponseSchema(name=\"price_value\",\n", " description=\"Extract any\\\n", " sentences about the value or \\\n", " price, and output them as a \\\n", " comma separated Python list.\")\n", "\n", "\n", "response_schemas = [gift_schema, \n", " delivery_days_schema,\n", " price_value_schema]\n", "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)\n", "format_instructions = output_parser.get_format_instructions()\n", "print(format_instructions)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u63d0\u793a\u6d88\u606f"]}, {"cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": ["messages = prompt.format_messages(text=customer_review, format_instructions=format_instructions)"]}, {"cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the productto arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\n", "\n", "text: \u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\n", "\n", "The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"gift\": string // Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\t\"delivery_days\": string // How many days did it take for the product to arrive? If this information is not found, output -1.\n", "\t\"price_value\": string // Extract any sentences about the value or price, and output them as a comma separated Python list.\n", "}\n", "```\n", "\n"]}], "source": ["print(messages[0].content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u63d0\u53d6\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["```json\n", "{\n", "\t\"gift\": false,\n", "\t\"delivery_days\": \"2\",\n", "\t\"price_value\": \"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"\n", "}\n", "```\n"]}], "source": ["response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 5\ufe0f\u20e3 \u4f7f\u7528\u8f93\u51fa\u89e3\u6790\u5668\u89e3\u6790\u8f93\u51fa"]}, {"cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [{"data": {"text/plain": ["{'gift': False, 'delivery_days': '2', 'price_value': '\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9'}"]}, "execution_count": 54, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict = output_parser.parse(response.content)\n", "output_dict"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udcdd \u5206\u6790\u4e0e\u603b\u7ed3\n", "`output_dict`\u7c7b\u578b\u4e3a\u5b57\u5178(`dict`), \u53ef\u76f4\u63a5\u4f7f\u7528`get`\u65b9\u6cd5\u3002\u8fd9\u6837\u7684\u8f93\u51fa\u66f4\u65b9\u4fbf\u4e0b\u6e38\u4efb\u52a1\u7684\u5904\u7406\u3002"]}, {"cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [{"data": {"text/plain": ["dict"]}, "execution_count": 55, "metadata": {}, "output_type": "execute_result"}], "source": ["type(output_dict)"]}, {"cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [{"data": {"text/plain": ["'2'"]}, "execution_count": 56, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict.get('delivery_days')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.4 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"\u793c\u7269\": string // \u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\t\"\u4ea4\u8d27\u5929\u6570\": string // \u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\t\"\u4ef7\u94b1\": string // \u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\n", "}\n", "```\n"]}], "source": ["# \u4e2d\u6587\n", "review_template_2 = \"\"\"\\\n", "\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\uff1a\n", "\n", "\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f\n", "\u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\n", "\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u5230\u8fbe\u9700\u8981\u591a\u5c11\u5929\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\n", "\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\n", "\n", "\u6587\u672c: {text}\n", "\n", "{format_instructions}\n", "\"\"\"\n", "\n", "from langchain.output_parsers import ResponseSchema\n", "from langchain.output_parsers import StructuredOutputParser\n", "\n", "gift_schema = ResponseSchema(name=\"\u793c\u7269\",\n", " description=\"\u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f\\\n", " \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c\\\n", " \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\")\n", "\n", "delivery_days_schema = ResponseSchema(name=\"\u4ea4\u8d27\u5929\u6570\",\n", " description=\"\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f\\\n", " \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\")\n", "\n", "price_value_schema = ResponseSchema(name=\"\u4ef7\u94b1\",\n", " description=\"\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\\\n", " \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\")\n", "\n", "\n", "response_schemas = [gift_schema, \n", " delivery_days_schema,\n", " price_value_schema]\n", "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)\n", "format_instructions = output_parser.get_format_instructions()\n", "print(format_instructions)"]}, {"cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the productto arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\n", "\n", "text: \u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\n", "\n", "The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"\u793c\u7269\": string // \u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\t\"\u4ea4\u8d27\u5929\u6570\": string // \u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\t\"\u4ef7\u94b1\": string // \u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\n", "}\n", "```\n", "\n"]}], "source": ["messages = prompt.format_messages(text=customer_review, format_instructions=format_instructions)\n", "print(messages[0].content)"]}, {"cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["```json\n", "{\n", "\t\"\u793c\u7269\": false,\n", "\t\"\u4ea4\u8d27\u5929\u6570\": \"\u4e24\u5929\u540e\",\n", "\t\"\u4ef7\u94b1\": \"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"\n", "}\n", "```\n"]}], "source": ["response = chat(messages)\n", "print(response.content)\n"]}, {"cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [{"data": {"text/plain": ["{'\u793c\u7269': False, '\u4ea4\u8d27\u5929\u6570': '\u4e24\u5929\u540e', '\u4ef7\u94b1': '\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9'}"]}, "execution_count": 60, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict = output_parser.parse(response.content)\n", "output_dict"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## \u56db\u3001\u8865\u5145\u6750\u6599"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 4.1 \u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct)\n", "\u53c2\u8003\u8d44\u6599\uff1a[ReAct (Reason+Act) prompting in OpenAI GPT and LangChain](https://tsmatz.wordpress.com/2023/03/07/react-with-openai-gpt-and-langchain/)"]}, {"cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [], "source": ["!pip install -q wikipedia"]}, {"cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "\u001b[32;1m\u001b[1;3mThought: I need to search David Chanoff and find the U.S. Navy admiral he collaborated with. Then I need to find the president under whom the admiral served as the ambassador to the United Kingdom.\n", "Action: Search[David Chanoff]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, \u0110o\u00e0n V\u0103n To\u1ea1i, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mDavid Chanoff has collaborated with several individuals, including Augustus A. White, Joycelyn Elders, \u0110o\u00e0n V\u0103n To\u1ea1i, William J. Crowe, Ariel Sharon, Kenneth Good, and Felix Zandman. I need to search each of these individuals to find the U.S. Navy admiral. \n", "Action: Search[Augustus A. White]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mAugustus A. White III (born June 4, 1936) is the Ellen and Melvin Gordon Distinguished Professor of Medical Education and Professor of Orthopedic Surgery at Harvard Medical School and a former Orthopaedic Surgeon-in-Chief at Beth Israel Hospital, Boston, Massachusetts. White was the first African American medical student at Stanford, surgical resident at Yale University, professor of medicine at Yale, and department head at a Harvard-affiliated hospital (Beth Israel Hospital).\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mAugustus A. White III is not a U.S. Navy admiral. I need to search the next individual, Joycelyn Elders.\n", "Action: Search[Joycelyn Elders]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mMinnie Joycelyn Elders (born Minnie Lee Jones; August 13, 1933) is an American pediatrician and public health administrator who served as Surgeon General of the United States from 1993 to 1994. A vice admiral in the Public Health Service Commissioned Corps, she was the second woman, second person of color, and first African American to serve as Surgeon General. \n", "Elders is best known for her frank discussion of her views on controversial issues such as drug legalization, masturbation, and distributing contraception in schools. She was forced to resign in December 1994 amidst controversy as a result of her views. She is currently a professor emerita of pediatrics at the University of Arkansas for Medical Sciences.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mJoycelyn Elders is a pediatrician and public health administrator, not a U.S. Navy admiral. I need to search the next individual, \u0110o\u00e0n V\u0103n To\u1ea1i.\n", "Action: Search[\u0110o\u00e0n V\u0103n To\u1ea1i]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3m\u0110o\u00e0n V\u0103n To\u1ea1i (1945 in Vietnam \u2013 November 2017 in California) was a Vietnamese-born naturalized American activist and the author of The Vietnamese Gulag (Simon & Schuster, 1986).\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3m\u0110o\u00e0n V\u0103n To\u1ea1i is an activist and author, not a U.S. Navy admiral. I need to search the next individual, William J. Crowe.\n", "Action: Search[William J. Crowe]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mWilliam James Crowe Jr. (January 2, 1925 \u2013 October 18, 2007) was a United States Navy admiral and diplomat who served as the 11th chairman of the Joint Chiefs of Staff under Presidents Ronald Reagan and George H. W. Bush, and as the ambassador to the United Kingdom and Chair of the Intelligence Oversight Board under President Bill Clinton.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mWilliam J. Crowe is a U.S. Navy admiral and diplomat. I need to find the president under whom he served as the ambassador to the United Kingdom.\n", "Action: Search[William J. Crowe ambassador to United Kingdom]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mWilliam James Crowe Jr. (January 2, 1925 \u2013 October 18, 2007) was a United States Navy admiral and diplomat who served as the 11th chairman of the Joint Chiefs of Staff under Presidents Ronald Reagan and George H. W. Bush, and as the ambassador to the United Kingdom and Chair of the Intelligence Oversight Board under President Bill Clinton.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mWilliam J. Crowe served as the ambassador to the United Kingdom under President Bill Clinton. So the answer is Bill Clinton.\n", "Action: Finish[Bill Clinton]\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Bill Clinton'"]}, "execution_count": 69, "metadata": {}, "output_type": "execute_result"}], "source": ["from langchain.docstore.wikipedia import Wikipedia\n", "from langchain.llms import OpenAI\n", "from langchain.agents import initialize_agent, Tool, AgentExecutor\n", "from langchain.agents.react.base import DocstoreExplorer\n", "\n", "docstore=DocstoreExplorer(Wikipedia())\n", "tools = [\n", " Tool(\n", " name=\"Search\",\n", " func=docstore.search,\n", " description=\"Search for a term in the docstore.\",\n", " ),\n", " Tool(\n", " name=\"Lookup\",\n", " func=docstore.lookup,\n", " description=\"Lookup a term in the docstore.\",\n", " )\n", "]\n", "\n", "# \u4f7f\u7528\u5927\u8bed\u8a00\u6a21\u578b\n", "llm = OpenAI(\n", " model_name=\"gpt-3.5-turbo\",\n", " temperature=0,\n", ")\n", "\n", "# \u521d\u59cb\u5316ReAct\u4ee3\u7406\n", "react = initialize_agent(tools, llm, agent=\"react-docstore\", verbose=True)\n", "agent_executor = AgentExecutor.from_agent_and_tools(\n", " agent=react.agent,\n", " tools=tools,\n", " verbose=True,\n", ")\n", "\n", "\n", "question = \"Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?\"\n", "agent_executor.run(question)"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# \u7b2c\u4e8c\u7ae0 \u6a21\u578b\uff0c\u63d0\u793a\u548c\u8f93\u51fa\u89e3\u91ca\u5668\n", "\n", " - [\u4e00\u3001\u8bbe\u7f6eOpenAI API Key](#\u4e00\u3001\u8bbe\u7f6eOpenAI-API-Key)\n", " - [\u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI](#\u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI)\n", " - [2.1 \u8ba1\u7b971+1](#2.1-\u8ba1\u7b971+1)\n", " - [2.2 \u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6](#2.2-\u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6)\n", " - [2.3 \u4e2d\u6587\u7248](#2.3-\u4e2d\u6587\u7248)\n", " - [\u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI](#\u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI)\n", " - [3.1 \u6a21\u578b](#3.1-\u6a21\u578b)\n", " - [3.2 \u63d0\u793a\u6a21\u677f](#3.2-\u63d0\u793a\u6a21\u677f)\n", " - [3.2.1 \u4f7f\u7528LangChain\u63d0\u793a\u6a21\u7248](#3.2.1-\u4f7f\u7528LangChain\u63d0\u793a\u6a21\u7248)\n", " - [3.2.2 \u4e2d\u6587\u7248](#3.2.2-\u4e2d\u6587\u7248)\n", " - [3.2.2 \u4e3a\u4ec0\u4e48\u9700\u8981\u63d0\u793a\u6a21\u7248](#3.2.2-\u4e3a\u4ec0\u4e48\u9700\u8981\u63d0\u793a\u6a21\u7248)\n", " - [3.3 \u8f93\u51fa\u89e3\u6790\u5668](#3.3-\u8f93\u51fa\u89e3\u6790\u5668)\n", " - [3.3.1 \u5982\u679c\u6ca1\u6709\u8f93\u51fa\u89e3\u6790\u5668](#3.3.1-\u5982\u679c\u6ca1\u6709\u8f93\u51fa\u89e3\u6790\u5668)\n", " - [3.3.2 \u4e2d\u6587\u7248](#3.3.2-\u4e2d\u6587\u7248)\n", " - [3.3.3 LangChain\u8f93\u51fa\u89e3\u6790\u5668](#3.3.3-LangChain\u8f93\u51fa\u89e3\u6790\u5668)\n", " - [3.3.4 \u4e2d\u6587\u7248](#3.3.4-\u4e2d\u6587\u7248)\n", " - [\u56db\u3001\u8865\u5145\u6750\u6599](#\u56db\u3001\u8865\u5145\u6750\u6599)\n", " - [4.1 \u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct)](#4.1-\u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct))\n"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e00\u3001\u8bbe\u7f6eOpenAI API Key\n", "\n", "\u767b\u9646 [OpenAI \u8d26\u6237](https://platform.openai.com/account/api-keys) \u83b7\u53d6API Key\uff0c\u7136\u540e\u5c06\u5176\u8bbe\u7f6e\u4e3a\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u5168\u5c40\u73af\u5883\u53d8\u91cf\uff0c\u53ef\u4ee5\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://zhuanlan.zhihu.com/p/627665725)\u3002\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u672c\u5730/\u9879\u76ee\u73af\u5883\u53d8\u91cf\uff0c\u5728\u672c\u6587\u4ef6\u76ee\u5f55\u4e0b\u521b\u5efa`.env`\u6587\u4ef6, \u6253\u5f00\u6587\u4ef6\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u3002\n", "\n", "

\n", " OPENAI_API_KEY=\"your_api_key\" \n", "

\n", " \n", " \u66ff\u6362\"your_api_key\"\u4e3a\u4f60\u81ea\u5df1\u7684 API Key"]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": ["# \u4e0b\u8f7d\u9700\u8981\u7684\u5305python-dotenv\u548copenai\n", "# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "!pip install -q python-dotenv\n", "!pip install -q openai"]}, {"cell_type": "code", "execution_count": 2, "metadata": {"tags": []}, "outputs": [], "source": ["import os\n", "import openai\n", "from dotenv import load_dotenv, find_dotenv\n", "\n", "# \u8bfb\u53d6\u672c\u5730/\u9879\u76ee\u7684\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "# find_dotenv()\u5bfb\u627e\u5e76\u5b9a\u4f4d.env\u6587\u4ef6\u7684\u8def\u5f84\n", "# load_dotenv()\u8bfb\u53d6\u8be5.env\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u52a0\u8f7d\u5230\u5f53\u524d\u7684\u8fd0\u884c\u73af\u5883\u4e2d \n", "# \u5982\u679c\u4f60\u8bbe\u7f6e\u7684\u662f\u5168\u5c40\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u884c\u4ee3\u7801\u5219\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n", "_ = load_dotenv(find_dotenv())\n", "\n", "# \u83b7\u53d6\u73af\u5883\u53d8\u91cf OPENAI_API_KEY\n", "openai.api_key = os.environ['OPENAI_API_KEY'] "]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e8c\u3001\u76f4\u63a5\u4f7f\u7528OpenAI\n", "\n", "\u6211\u4eec\u5148\u4ece\u76f4\u63a5\u8c03\u7528OpenAI\u7684API\u5f00\u59cb\u3002\n", "\n", "`get_completion`\u51fd\u6570\u662f\u57fa\u4e8e`openai`\u7684\u5c01\u88c5\u51fd\u6570\uff0c\u5bf9\u4e8e\u7ed9\u5b9a\u63d0\u793a\uff08prompt\uff09\u8f93\u51fa\u76f8\u5e94\u7684\u56de\u7b54\u3002\u5176\u5305\u542b\u4e24\u4e2a\u53c2\u6570\n", " \n", " - `prompt` \u5fc5\u9700\u8f93\u5165\u53c2\u6570\u3002 \u4f60\u7ed9\u6a21\u578b\u7684**\u63d0\u793a\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u95ee\u9898\uff0c\u53ef\u4ee5\u662f\u4f60\u9700\u8981\u6a21\u578b\u5e2e\u52a9\u4f60\u505a\u7684\u4e8b**\uff08\u6539\u53d8\u6587\u672c\u5199\u4f5c\u98ce\u683c\uff0c\u7ffb\u8bd1\uff0c\u56de\u590d\u6d88\u606f\u7b49\u7b49\uff09\u3002\n", " - `model` \u975e\u5fc5\u9700\u8f93\u5165\u53c2\u6570\u3002\u9ed8\u8ba4\u4f7f\u7528gpt-3.5-turbo\u3002\u4f60\u4e5f\u53ef\u4ee5\u9009\u62e9\u5176\u4ed6\u6a21\u578b\u3002\n", " \n", "\u8fd9\u91cc\u7684\u63d0\u793a\u5bf9\u5e94\u6211\u4eec\u7ed9chatgpt\u7684\u95ee\u9898\uff0c\u51fd\u6570\u7ed9\u51fa\u7684\u8f93\u51fa\u5219\u5bf9\u5e94chatpgt\u7ed9\u6211\u4eec\u7684\u7b54\u6848\u3002"]}, {"cell_type": "code", "execution_count": 3, "metadata": {"tags": []}, "outputs": [], "source": ["def get_completion(prompt, model=\"gpt-3.5-turbo\"):\n", " \n", " messages = [{\"role\": \"user\", \"content\": prompt}]\n", " \n", " response = openai.ChatCompletion.create(\n", " model=model,\n", " messages=messages,\n", " temperature=0, \n", " )\n", " return response.choices[0].message[\"content\"]"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.1 \u8ba1\u7b971+1\n", "\n", "\u6211\u4eec\u6765\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50 - \u5206\u522b\u7528\u4e2d\u82f1\u6587\u95ee\u95ee\u6a21\u578b\n", "\n", "- \u4e2d\u6587\u63d0\u793a(Prompt in Chinese)\uff1a `1+1\u662f\u4ec0\u4e48\uff1f`\n", "- \u82f1\u6587\u63d0\u793a(Prompt in English)\uff1a `What is 1+1?`"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"text/plain": ["'1+1\u7b49\u4e8e2\u3002'"]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "get_completion(\"1+1\u662f\u4ec0\u4e48\uff1f\")"]}, {"cell_type": "code", "execution_count": 5, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["'1+1 equals 2.'"]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u82f1\u6587\n", "get_completion(\"What is 1+1?\")"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.2 \u7528\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u6d77\u76d7\u90ae\u4ef6\n", "\n", "\u4e0a\u9762\u7684\u7b80\u5355\u4f8b\u5b50\uff0c\u6a21\u578b`gpt-3.5-turbo`\u5bf9\u6211\u4eec\u7684\u5173\u4e8e1+1\u662f\u4ec0\u4e48\u7684\u63d0\u95ee\u7ed9\u51fa\u4e86\u56de\u7b54\u3002\n", "\n", "\u73b0\u5728\u6211\u4eec\u6765\u770b\u4e00\u4e2a\u590d\u6742\u4e00\u70b9\u7684\u4f8b\u5b50\uff1a \n", "\n", "\u5047\u8bbe\u6211\u4eec\u662f\u7535\u5546\u516c\u53f8\u5458\u5de5\uff0c\u6211\u4eec\u7684\u987e\u5ba2\u662f\u4e00\u540d\u6d77\u76d7A\uff0c\u4ed6\u5728\u6211\u4eec\u7684\u7f51\u7ad9\u4e0a\u4e70\u4e86\u4e00\u4e2a\u69a8\u6c41\u673a\u7528\u6765\u505a\u5976\u6614\uff0c\u5728\u5236\u4f5c\u5976\u6614\u7684\u8fc7\u7a0b\u4e2d\uff0c\u5976\u6614\u7684\u76d6\u5b50\u98de\u4e86\u51fa\u53bb\uff0c\u5f04\u5f97\u53a8\u623f\u5899\u4e0a\u5230\u5904\u90fd\u662f\u3002\u4e8e\u662f\u6d77\u76d7A\u7ed9\u6211\u4eec\u7684\u5ba2\u670d\u4e2d\u5fc3\u5199\u6765\u4ee5\u4e0b\u90ae\u4ef6\uff1a`customer_email`"]}, {"cell_type": "code", "execution_count": 6, "metadata": {"tags": []}, "outputs": [], "source": ["customer_email = \"\"\"\n", "Arrr, I be fuming that me blender lid \\\n", "flew off and splattered me kitchen walls \\\n", "with smoothie! And to make matters worse,\\\n", "the warranty don't cover the cost of \\\n", "cleaning up me kitchen. I need yer help \\\n", "right now, matey!\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u6211\u4eec\u7684\u5ba2\u670d\u4eba\u5458\u5bf9\u4e8e\u6d77\u76d7\u7684\u63aa\u8f9e\u8868\u8fbe\u89c9\u5f97\u6709\u70b9\u96be\u4ee5\u7406\u89e3\u3002 \u73b0\u5728\u6211\u4eec\u60f3\u8981\u5b9e\u73b0\u4e24\u4e2a\u5c0f\u76ee\u6807\uff1a\n", "\n", "- \u8ba9\u6a21\u578b\u7528\u7f8e\u5f0f\u82f1\u8bed\u7684\u8868\u8fbe\u65b9\u5f0f\u5c06\u6d77\u76d7\u7684\u90ae\u4ef6\u8fdb\u884c\u7ffb\u8bd1\uff0c\u5ba2\u670d\u4eba\u5458\u53ef\u4ee5\u66f4\u597d\u7406\u89e3\u3002*\u8fd9\u91cc\u6d77\u76d7\u7684\u82f1\u6587\u8868\u8fbe\u53ef\u4ee5\u7406\u89e3\u4e3a\u82f1\u6587\u7684\u65b9\u8a00\uff0c\u5176\u4e0e\u7f8e\u5f0f\u82f1\u8bed\u7684\u5173\u7cfb\uff0c\u5c31\u5982\u56db\u5ddd\u8bdd\u4e0e\u666e\u901a\u8bdd\u7684\u5173\u7cfb\u3002\n", "- \u8ba9\u6a21\u578b\u5728\u7ffb\u8bd1\u662f\u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\u8fdb\u884c\u8868\u8fbe\uff0c\u5ba2\u670d\u4eba\u5458\u7684\u5fc3\u60c5\u4e5f\u4f1a\u66f4\u597d\u3002\n", "\n", "\u6839\u636e\u8fd9\u4e24\u4e2a\u5c0f\u76ee\u6807\uff0c\u5b9a\u4e49\u4e00\u4e0b\u6587\u672c\u8868\u8fbe\u98ce\u683c\uff1a`style`"]}, {"cell_type": "code", "execution_count": 7, "metadata": {"tags": []}, "outputs": [], "source": ["# \u7f8e\u5f0f\u82f1\u8bed + \u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "style = \"\"\"American English \\\n", "in a calm and respectful tone\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0b\u4e00\u6b65\u9700\u8981\u505a\u7684\u662f\u5c06`customer_email`\u548c`style`\u7ed3\u5408\u8d77\u6765\u6784\u9020\u6211\u4eec\u7684\u63d0\u793a:`prompt`"]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": ["# \u975e\u6b63\u5f0f\u7528\u8bed\n", "customer_email = \"\"\" \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\\\n", "\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\\\n", "\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\\\n", "\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\\\n", "\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 9, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Translate the text that is delimited by triple backticks \n", "into a style that is American English in a calm and respectful tone\n", ".\n", "text: ``` \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "```\n", "\n"]}], "source": ["# \u8981\u6c42\u6a21\u578b\u6839\u636e\u7ed9\u51fa\u7684\u8bed\u8c03\u8fdb\u884c\u8f6c\u5316\n", "prompt = f\"\"\"Translate the text \\\n", "that is delimited by triple backticks \n", "into a style that is {style}.\n", "text: ```{customer_email}```\n", "\"\"\"\n", "\n", "print(prompt)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["`prompt` \u6784\u9020\u597d\u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u8c03\u7528`get_completion`\u5f97\u5230\u6211\u4eec\u60f3\u8981\u7684\u7ed3\u679c - \u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\uff0c\u7f8e\u5f0f\u82f1\u8bed\u8868\u8fbe\u7684\u6d77\u76d7\u8bed\u8a00\u90ae\u4ef6"]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": ["response = get_completion(prompt)"]}, {"cell_type": "code", "execution_count": 11, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["\"Oh, I'm really frustrated because the lid of my blender fell off and splattered the milkshake all over the kitchen wall! To make matters worse, the warranty doesn't cover the cost of cleaning the kitchen. I could really use your help right now, buddy!\""]}, "execution_count": 11, "metadata": {}, "output_type": "execute_result"}], "source": ["response"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5bf9\u6bd4\u8bed\u8a00\u98ce\u683c\u8f6c\u6362\u524d\u540e\uff0c\u7528\u8bcd\u66f4\u4e3a\u6b63\u5f0f\uff0c\u66ff\u6362\u4e86\u6781\u7aef\u60c5\u7eea\u7684\u8868\u8fbe\uff0c\u5e76\u8868\u8fbe\u4e86\u611f\u8c22\u3002\n", "\n", "\u2728 \u4f60\u53ef\u4ee5\u5c1d\u8bd5\u4fee\u6539\u63d0\u793a\uff0c\u770b\u53ef\u4ee5\u5f97\u5230\u4ec0\u4e48\u4e0d\u4e00\u6837\u7684\u7ed3\u679c\ud83d\ude09"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 2.3 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": ["# \u666e\u901a\u8bdd + \u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "style = \"\"\"\u6b63\u5f0f\u666e\u901a\u8bdd \\\n", "\u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u6b63\u5f0f\u666e\u901a\u8bdd \u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u8c03\n", "\u98ce\u683c\u3002\n", "\u6587\u672c: ``` \n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "```\n", "\n"]}], "source": ["# \u8981\u6c42\u6a21\u578b\u6839\u636e\u7ed9\u51fa\u7684\u8bed\u8c03\u8fdb\u884c\u8f6c\u5316\n", "prompt = f\"\"\"\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\\\n", "\u7ffb\u8bd1\u6210\u4e00\u79cd{style}\u98ce\u683c\u3002\n", "\u6587\u672c: ```{customer_email}```\n", "\"\"\"\n", "\n", "print(prompt)\n", "\n"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["'\u5c0a\u656c\u7684\u670b\u53cb\u4eec\uff0c\u6211\u611f\u5230\u975e\u5e38\u4e0d\u5b89\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u670d\u52a1\u5e76\u4e0d\u5305\u542b\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u6b64\u523b\uff0c\u6211\u771f\u8bda\u5730\u8bf7\u6c42\u5404\u4f4d\u7684\u5e2e\u52a9\uff0c\u670b\u53cb\u4eec\uff01'"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["response = get_completion(prompt)\n", "\n", "response"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["## \u4e09\u3001\u901a\u8fc7LangChain\u4f7f\u7528OpenAI\n", "\n", "\u5728\u524d\u9762\u4e00\u90e8\u5206\uff0c\u6211\u4eec\u901a\u8fc7\u5c01\u88c5\u51fd\u6570`get_completion`\u76f4\u63a5\u8c03\u7528\u4e86OpenAI\u5b8c\u6210\u4e86\u5bf9\u65b9\u8a00\u90ae\u4ef6\u8fdb\u884c\u4e86\u7684\u7ffb\u8bd1\uff0c\u5f97\u5230\u7528\u5e73\u548c\u5c0a\u91cd\u7684\u8bed\u6c14\u3001\u6b63\u5f0f\u7684\u666e\u901a\u8bdd\u8868\u8fbe\u7684\u90ae\u4ef6\u3002\n", "\n", "\u8ba9\u6211\u4eec\u5c1d\u8bd5\u4f7f\u7528LangChain\u6765\u5b9e\u73b0\u76f8\u540c\u7684\u529f\u80fd\u3002"]}, {"cell_type": "code", "execution_count": 15, "metadata": {"tags": []}, "outputs": [], "source": ["# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "# --upgrade \u8ba9\u6211\u4eec\u53ef\u4ee5\u5b89\u88c5\u5230\u6700\u65b0\u7248\u672c\u7684 langchain\n", "!pip install -q --upgrade langchain"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["### 3.1 \u6a21\u578b\n", "\n", "\u4ece`langchain.chat_models`\u5bfc\u5165`OpenAI`\u7684\u5bf9\u8bdd\u6a21\u578b`ChatOpenAI`\u3002 \u9664\u53bbOpenAI\u4ee5\u5916\uff0c`langchain.chat_models`\u8fd8\u96c6\u6210\u4e86\u5176\u4ed6\u5bf9\u8bdd\u6a21\u578b\uff0c\u66f4\u591a\u7ec6\u8282\u53ef\u4ee5\u67e5\u770b[Langchain\u5b98\u65b9\u6587\u6863](https://python.langchain.com/en/latest/modules/models/chat/integrations.html)\u3002"]}, {"cell_type": "code", "execution_count": 16, "metadata": {"tags": []}, "outputs": [], "source": ["from langchain.chat_models import ChatOpenAI"]}, {"cell_type": "code", "execution_count": 17, "metadata": {"tags": []}, "outputs": [{"data": {"text/plain": ["ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, client=, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None)"]}, "execution_count": 17, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u8fd9\u91cc\u6211\u4eec\u5c06\u53c2\u6570temperature\u8bbe\u7f6e\u4e3a0.0\uff0c\u4ece\u800c\u51cf\u5c11\u751f\u6210\u7b54\u6848\u7684\u968f\u673a\u6027\u3002\n", "# \u5982\u679c\u4f60\u60f3\u8981\u6bcf\u6b21\u5f97\u5230\u4e0d\u4e00\u6837\u7684\u6709\u65b0\u610f\u7684\u7b54\u6848\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u8c03\u6574\u8be5\u53c2\u6570\u3002\n", "chat = ChatOpenAI(temperature=0.0)\n", "chat"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0a\u9762\u7684\u8f93\u51fa\u663e\u793aChatOpenAI\u7684\u9ed8\u8ba4\u6a21\u578b\u4e3a`gpt-3.5-turbo`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 3.2 \u63d0\u793a\u6a21\u677f\n", "\n", "\u5728\u524d\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u901a\u8fc7[f\u5b57\u7b26\u4e32](https://docs.python.org/zh-cn/3/tutorial/inputoutput.html#tut-f-strings)\u628aPython\u8868\u8fbe\u5f0f\u7684\u503c`style`\u548c`customer_email`\u6dfb\u52a0\u5230`prompt`\u5b57\u7b26\u4e32\u5185\u3002\n", "\n", "```python\n", "prompt = f\"\"\"Translate the text \\\n", "that is delimited by triple backticks \n", "into a style that is {style}.\n", "text: ```{customer_email}```\n", "\"\"\"\n", "```\n", "`langchain`\u63d0\u4f9b\u4e86\u63a5\u53e3\u65b9\u4fbf\u5feb\u901f\u7684\u6784\u9020\u548c\u4f7f\u7528\u63d0\u793a\u3002\u73b0\u5728\u6211\u4eec\u6765\u770b\u770b\u5982\u4f55\u4f7f\u7528`langchain`\u6765\u6784\u9020\u63d0\u793a\u3002"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["#### 3.2.1 \u4f7f\u7528LangChain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32\n", "\u6211\u4eec\u6784\u9020\u4e00\u4e2a\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32\uff1a`template_string`"]}, {"cell_type": "code", "execution_count": 18, "metadata": {"tags": []}, "outputs": [], "source": ["template_string = \"\"\"Translate the text \\\n", "that is delimited by triple backticks \\\n", "into a style that is {style}. \\\n", "text: ```{text}```\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020LangChain\u63d0\u793a\u6a21\u7248\n", "\u6211\u4eec\u8c03\u7528`ChatPromptTemplatee.from_template()`\u51fd\u6570\u5c06\u4e0a\u9762\u7684\u63d0\u793a\u6a21\u7248\u5b57\u7b26`template_string`\u8f6c\u6362\u4e3a\u63d0\u793a\u6a21\u7248`prompt_template`"]}, {"cell_type": "code", "execution_count": 19, "metadata": {"tags": []}, "outputs": [], "source": ["from langchain.prompts import ChatPromptTemplate\n", "prompt_template = ChatPromptTemplate.from_template(template_string)"]}, {"cell_type": "code", "execution_count": 20, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['style', 'text'] output_parser=None partial_variables={} template='Translate the text that is delimited by triple backticks into a style that is {style}. text: ```{text}```\\n' template_format='f-string' validate_template=True\n"]}], "source": ["print(prompt_template.messages[0].prompt)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4ece\u4e0a\u9762\u7684\u8f93\u51fa\u53ef\u4ee5\u770b\u51fa\uff0c`prompt_template` \u6709\u4e24\u4e2a\u8f93\u5165\u53d8\u91cf\uff1a `style` \u548c `text`\u3002"]}, {"cell_type": "code", "execution_count": 21, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["['style', 'text']\n"]}], "source": ["print(prompt_template.messages[0].prompt.input_variables)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u5ba2\u6237\u6d88\u606f\u63d0\u793a\n", "\n", "langchain\u63d0\u793a\u6a21\u7248`prompt_template`\u9700\u8981\u4e24\u4e2a\u8f93\u5165\u53d8\u91cf\uff1a `style` \u548c `text`\u3002 \u8fd9\u91cc\u5206\u522b\u5bf9\u5e94 \n", "- `customer_style`: \u6211\u4eec\u60f3\u8981\u7684\u987e\u5ba2\u90ae\u4ef6\u98ce\u683c\n", "- `customer_email`: \u987e\u5ba2\u7684\u539f\u59cb\u90ae\u4ef6\u6587\u672c\u3002"]}, {"cell_type": "code", "execution_count": 22, "metadata": {"tags": []}, "outputs": [], "source": ["customer_style = \"\"\"American English \\\n", "in a calm and respectful tone\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 23, "metadata": {"tags": []}, "outputs": [], "source": ["customer_email = \"\"\"\n", "Arrr, I be fuming that me blender lid \\\n", "flew off and splattered me kitchen walls \\\n", "with smoothie! And to make matters worse, \\\n", "the warranty don't cover the cost of \\\n", "cleaning up me kitchen. I need yer help \\\n", "right now, matey!\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5bf9\u4e8e\u7ed9\u5b9a\u7684`customer_style`\u548c`customer_email`, \u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u63d0\u793a\u6a21\u7248`prompt_template`\u7684`format_messages`\u65b9\u6cd5\u751f\u6210\u60f3\u8981\u7684\u5ba2\u6237\u6d88\u606f`customer_messages`\u3002"]}, {"cell_type": "code", "execution_count": 24, "metadata": {"tags": []}, "outputs": [], "source": ["customer_messages = prompt_template.format_messages(\n", " style=customer_style,\n", " text=customer_email)"]}, {"cell_type": "code", "execution_count": 25, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n"]}], "source": ["print(type(customer_messages))\n", "print(type(customer_messages[0]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u53ef\u4ee5\u770b\u51fa`customer_messages`\u53d8\u91cf\u7c7b\u578b\u4e3a\u5217\u8868(`list`)\uff0c\u800c\u5217\u8868\u91cc\u7684\u5143\u7d20\u53d8\u91cf\u7c7b\u578b\u4e3alangchain\u81ea\u5b9a\u4e49\u6d88\u606f(`langchain.schema.HumanMessage`)\u3002\n", "\n", "\u6253\u5370\u7b2c\u4e00\u4e2a\u5143\u7d20\u53ef\u4ee5\u5f97\u5230\u5982\u4e0b:"]}, {"cell_type": "code", "execution_count": 26, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["content=\"Translate the text that is delimited by triple backticks into a style that is American English in a calm and respectful tone\\n. text: ```\\nArrr, I be fuming that me blender lid flew off and splattered me kitchen walls with smoothie! And to make matters worse, the warranty don't cover the cost of cleaning up me kitchen. I need yer help right now, matey!\\n```\\n\" additional_kwargs={} example=False\n"]}], "source": ["print(customer_messages[0])"]}, {"cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["content='\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u6b63\u5f0f\u666e\u901a\u8bdd \u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u6c14\\n\u98ce\u683c\u3002\u6587\u672c: ```\\n\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\\n```\\n' additional_kwargs={} example=False\n"]}], "source": ["# \u4e2d\u6587\u63d0\u793a\n", "from langchain.prompts import ChatPromptTemplate\n", "\n", "template_string = \"\"\"\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\\\n", "\u7ffb\u8bd1\u6210\u4e00\u79cd{style}\u98ce\u683c\u3002\\\n", "\u6587\u672c: ```{text}```\n", "\"\"\"\n", "prompt_template = ChatPromptTemplate.from_template(template_string)\n", "\n", "customer_style = \"\"\"\u6b63\u5f0f\u666e\u901a\u8bdd \\\n", "\u7528\u4e00\u4e2a\u5e73\u9759\u3001\u5c0a\u656c\u7684\u8bed\u6c14\n", "\"\"\"\n", "\n", "customer_email = \"\"\"\n", "\u963f\uff0c\u6211\u5f88\u751f\u6c14\uff0c\\\n", "\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u6389\u4e86\uff0c\\\n", "\u628a\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u4e0a\uff01\\\n", "\u66f4\u7cdf\u7cd5\u7684\u662f\uff0c\u4fdd\u4fee\u4e0d\u5305\u62ec\u6253\u626b\u53a8\u623f\u7684\u8d39\u7528\u3002\\\n", "\u6211\u73b0\u5728\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u4f19\u8ba1\uff01\n", "\"\"\"\n", "\n", "customer_messages = prompt_template.format_messages(\n", " style=customer_style,\n", " text=customer_email)\n", "\n", "\n", "print(customer_messages[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u8f6c\u6362\u5ba2\u6237\u6d88\u606f\u98ce\u683c\n", "\n", "\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u8c03\u7528[\u6a21\u578b](#model)\u90e8\u5206\u5b9a\u4e49\u7684chat\u6a21\u578b\u6765\u5b9e\u73b0\u8f6c\u6362\u5ba2\u6237\u6d88\u606f\u98ce\u683c\u3002\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5df2\u7ecf\u5b9e\u73b0\u4e86\u5728\u524d\u4e00\u90e8\u5206\u7684\u4efb\u52a1\u3002"]}, {"cell_type": "code", "execution_count": 28, "metadata": {"tags": []}, "outputs": [], "source": ["customer_response = chat(customer_messages)"]}, {"cell_type": "code", "execution_count": 29, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u4f19\u8ba1\uff0c\u6211\u611f\u5230\u975e\u5e38\u6124\u6012\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u5e76\u4e0d\u5305\u62ec\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u73b0\u5728\uff0c\u6211\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u8bf7\u4f60\u7ed9\u4e88\u63f4\u624b\uff01\n"]}], "source": ["print(customer_response.content)"]}, {"cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u4f19\u8ba1\uff0c\u6211\u611f\u5230\u975e\u5e38\u6124\u6012\uff0c\u56e0\u4e3a\u6211\u7684\u6405\u62cc\u673a\u76d6\u5b50\u4e0d\u614e\u6389\u843d\uff0c\u5bfc\u81f4\u5976\u6614\u6e85\u5230\u4e86\u53a8\u623f\u7684\u5899\u58c1\u4e0a\uff01\u66f4\u52a0\u4ee4\u4eba\u7cdf\u5fc3\u7684\u662f\uff0c\u4fdd\u4fee\u5e76\u4e0d\u5305\u62ec\u53a8\u623f\u6e05\u6d01\u7684\u8d39\u7528\u3002\u73b0\u5728\uff0c\u6211\u9700\u8981\u4f60\u7684\u5e2e\u52a9\uff0c\u8bf7\u4f60\u7ed9\u4e88\u63f4\u624b\uff01\n"]}], "source": ["print(customer_response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 5\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u56de\u590d\u6d88\u606f\u63d0\u793a\n", "\n", "\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u66f4\u8fdb\u4e00\u6b65\uff0c\u5c06\u5ba2\u670d\u4eba\u5458\u56de\u590d\u7684\u6d88\u606f\uff0c\u8f6c\u6362\u4e3a\u6d77\u76d7\u7684\u8bed\u8a00\u98ce\u683c\uff0c\u5e76\u786e\u4fdd\u6d88\u606f\u6bd4\u8f83\u6709\u793c\u8c8c\u3002 \n", "\n", "\u8fd9\u91cc\uff0c\u6211\u4eec\u53ef\u4ee5\u7ee7\u7eed\u4f7f\u7528\u7b2c2\ufe0f\u20e3\u6b65\u6784\u9020\u7684langchain\u63d0\u793a\u6a21\u7248\uff0c\u6765\u83b7\u5f97\u6211\u4eec\u56de\u590d\u6d88\u606f\u63d0\u793a\u3002"]}, {"cell_type": "code", "execution_count": 31, "metadata": {"tags": []}, "outputs": [], "source": ["service_reply = \"\"\"Hey there customer, \\\n", "the warranty does not cover \\\n", "cleaning expenses for your kitchen \\\n", "because it's your fault that \\\n", "you misused your blender \\\n", "by forgetting to put the lid on before \\\n", "starting the blender. \\\n", "Tough luck! See ya!\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": ["service_style_pirate = \"\"\"\\\n", "a polite tone \\\n", "that speaks in English Pirate\\\n", "\"\"\""]}, {"cell_type": "code", "execution_count": 33, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cda polite tone that speaks in English Pirate\u98ce\u683c\u3002\u6587\u672c: ```Hey there customer, the warranty does not cover cleaning expenses for your kitchen because it's your fault that you misused your blender by forgetting to put the lid on before starting the blender. Tough luck! See ya!\n", "```\n", "\n"]}], "source": ["service_messages = prompt_template.format_messages(\n", " style=service_style_pirate,\n", " text=service_reply)\n", "\n", "print(service_messages[0].content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 6\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u8f6c\u6362\u56de\u590d\u6d88\u606f\u98ce\u683c\n", "\n", "\u8c03\u7528[\u6a21\u578b](#model)\u90e8\u5206\u5b9a\u4e49\u7684chat\u6a21\u578b\u6765\u8f6c\u6362\u56de\u590d\u6d88\u606f\u98ce\u683c"]}, {"cell_type": "code", "execution_count": 34, "metadata": {"tags": []}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Ahoy there, matey! I regret to inform ye, valued customer, that the warranty be not coverin' the expenses o' cleanin' yer galley due to yer own negligence. 'Tis yer own fault, ye see, fer ye be misusin' yer blender by forgettin' to secure the lid afore settin' it in motion. Aye, 'tis a tough break, indeed! Fare thee well, me heartie!\n"]}], "source": ["service_response = chat(service_messages)\n", "print(service_response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.2.2 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u628a\u7531\u4e09\u4e2a\u53cd\u5f15\u53f7\u5206\u9694\u7684\u6587\u672c\u7ffb\u8bd1\u6210\u4e00\u79cd\u4e00\u4e2a\u6709\u793c\u8c8c\u7684\u8bed\u6c14 \u4f7f\u7528\u6b63\u5f0f\u7684\u666e\u901a\u8bdd \u98ce\u683c\u3002\u6587\u672c: ```\u563f\uff0c\u987e\u5ba2\uff0c \u4fdd\u4fee\u4e0d\u5305\u62ec\u53a8\u623f\u7684\u6e05\u6d01\u8d39\u7528\uff0c \u56e0\u4e3a\u60a8\u5728\u542f\u52a8\u6405\u62cc\u673a\u4e4b\u524d \u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u8bef\u7528\u6405\u62cc\u673a, \u8fd9\u662f\u60a8\u7684\u9519\u3002 \u5012\u9709\uff01 \u518d\u89c1\uff01\n", "```\n", "\n"]}], "source": ["service_reply = \"\"\"\u563f\uff0c\u987e\u5ba2\uff0c \\\n", "\u4fdd\u4fee\u4e0d\u5305\u62ec\u53a8\u623f\u7684\u6e05\u6d01\u8d39\u7528\uff0c \\\n", "\u56e0\u4e3a\u60a8\u5728\u542f\u52a8\u6405\u62cc\u673a\u4e4b\u524d \\\n", "\u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u8bef\u7528\u6405\u62cc\u673a, \\\n", "\u8fd9\u662f\u60a8\u7684\u9519\u3002 \\\n", "\u5012\u9709\uff01 \u518d\u89c1\uff01\n", "\"\"\"\n", "\n", "service_style_pirate = \"\"\"\\\n", "\u4e00\u4e2a\u6709\u793c\u8c8c\u7684\u8bed\u6c14 \\\n", "\u4f7f\u7528\u6b63\u5f0f\u7684\u666e\u901a\u8bdd \\\n", "\"\"\"\n", "service_messages = prompt_template.format_messages(\n", " style=service_style_pirate,\n", " text=service_reply)\n", "\n", "print(service_messages[0].content)"]}, {"cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u5c0a\u656c\u7684\u987e\u5ba2\uff0c\u5f88\u62b1\u6b49\u544a\u77e5\u60a8\uff0c\u4fdd\u4fee\u670d\u52a1\u4e0d\u5305\u542b\u53a8\u623f\u6e05\u6d01\u8d39\u7528\u3002\u8fd9\u662f\u56e0\u4e3a\u5728\u60a8\u4f7f\u7528\u6405\u62cc\u673a\u4e4b\u524d\uff0c\u4e0d\u614e\u5fd8\u8bb0\u76d6\u4e0a\u76d6\u5b50\u800c\u5bfc\u81f4\u8bef\u7528\u6405\u62cc\u673a\uff0c\u8fd9\u5c5e\u4e8e\u60a8\u7684\u758f\u5ffd\u3002\u975e\u5e38\u9057\u61be\uff01\u795d\u60a8\u4e00\u5207\u987a\u5229\uff01\u518d\u89c1\uff01\n"]}], "source": ["service_response = chat(service_messages)\n", "print(service_response.content)"]}, {"cell_type": "markdown", "metadata": {"tags": []}, "source": ["#### 3.2.2 \u4e3a\u4ec0\u4e48\u9700\u8981\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5728\u5e94\u7528\u4e8e\u6bd4\u8f83\u590d\u6742\u7684\u573a\u666f\u65f6\uff0c\u63d0\u793a\u53ef\u80fd\u4f1a\u975e\u5e38\u957f\u5e76\u4e14\u5305\u542b\u6d89\u53ca\u8bb8\u591a\u7ec6\u8282\u3002**\u4f7f\u7528\u63d0\u793a\u6a21\u7248\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u66f4\u4e3a\u65b9\u4fbf\u5730\u91cd\u590d\u4f7f\u7528\u8bbe\u8ba1\u597d\u7684\u63d0\u793a**\u3002"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u4e0b\u9762\u7ed9\u51fa\u4e86\u4e00\u4e2a\u6bd4\u8f83\u957f\u7684\u63d0\u793a\u6a21\u7248\u6848\u4f8b\u3002\u5b66\u751f\u4eec\u7ebf\u4e0a\u5b66\u4e60\u5e76\u63d0\u4ea4\u4f5c\u4e1a\uff0c\u901a\u8fc7\u4ee5\u4e0b\u7684\u63d0\u793a\u6765\u5b9e\u73b0\u5bf9\u5b66\u751f\u7684\u63d0\u4ea4\u7684\u4f5c\u4e1a\u7684\u8bc4\u5206\u3002"]}, {"cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": ["# \u82f1\u6587\u7248\n", "prompt = \"\"\" Your task is to determine if the student's solution is correct or not\n", "\n", " To solve the problem do the following:\n", " - First, workout your own solution to the problem\n", " - Then compare your solution to the student's solution \n", " and evaluate if the sudtent's solution is correct or not.\n", " ...\n", " Use the following format:\n", " Question:\n", " ```\n", " question here\n", " ```\n", " Student's solution:\n", " ```\n", " student's solution here\n", " ```\n", " Actual solution:\n", " ```\n", " ...\n", " steps to work out the solution and your solution here\n", " ```\n", " Is the student's solution the same as acutal solution \\\n", " just calculated:\n", " ```\n", " yes or no\n", " ```\n", " Student grade\n", " ```\n", " correct or incorrect\n", " ```\n", " \n", " Question:\n", " ```\n", " {question}\n", " ```\n", " Student's solution:\n", " ```\n", " {student's solution}\n", " ```\n", " Actual solution:\n", " \n", " \"\"\""]}, {"cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\u7248\n", "prompt = \"\"\" \u4f60\u7684\u4efb\u52a1\u662f\u5224\u65ad\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u662f\u6b63\u786e\u7684\u8fd8\u662f\u4e0d\u6b63\u786e\u7684\n", "\n", "\u8981\u89e3\u51b3\u8be5\u95ee\u9898\uff0c\u8bf7\u6267\u884c\u4ee5\u4e0b\u64cd\u4f5c\uff1a\n", " - \u9996\u5148\uff0c\u5236\u5b9a\u81ea\u5df1\u7684\u95ee\u9898\u89e3\u51b3\u65b9\u6848\n", " - \u7136\u540e\u5c06\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u4e0e\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u8fdb\u884c\u6bd4\u8f83\n", " \u5e76\u8bc4\u4f30\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u662f\u5426\u6b63\u786e\u3002\n", "...\n", "\u4f7f\u7528\u4e0b\u9762\u7684\u683c\u5f0f:\n", "\n", "\u95ee\u9898:\n", "```\n", "\u95ee\u9898\u6587\u672c\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848:\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u6587\u672c\n", "```\n", "\u5b9e\u9645\u89e3\u51b3\u65b9\u6848:\n", "```\n", "...\n", "\u5236\u5b9a\u89e3\u51b3\u65b9\u6848\u7684\u6b65\u9aa4\u4ee5\u53ca\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u8bf7\u53c2\u89c1\u6b64\u5904\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848\u548c\u5b9e\u9645\u89e3\u51b3\u65b9\u6848\u662f\u5426\u76f8\u540c \\\n", "\u53ea\u8ba1\u7b97\uff1a\n", "```\n", "\u662f\u6216\u8005\u4e0d\u662f\n", "```\n", "\u5b66\u751f\u7684\u6210\u7ee9\n", "```\n", "\u6b63\u786e\u6216\u8005\u4e0d\u6b63\u786e\n", "```\n", "\n", "\u95ee\u9898:\n", "```\n", "{question}\n", "```\n", "\u5b66\u751f\u7684\u89e3\u51b3\u65b9\u6848:\n", "```\n", "{student's solution}\n", "```\n", "\u5b9e\u9645\u89e3\u51b3\u65b9\u6848:\n", "\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {"jp-MarkdownHeadingCollapsed": true, "tags": []}, "source": ["\u6b64\u5916\uff0cLangChain\u8fd8\u63d0\u4f9b\u4e86\u63d0\u793a\u6a21\u7248\u7528\u4e8e\u4e00\u4e9b\u5e38\u7528\u573a\u666f\u3002\u6bd4\u5982\u81ea\u52a8\u6458\u8981\u3001\u95ee\u7b54\u3001\u8fde\u63a5\u5230SQL\u6570\u636e\u5e93\u3001\u8fde\u63a5\u5230\u4e0d\u540c\u7684API. \u901a\u8fc7\u4f7f\u7528LongChain\u5185\u7f6e\u7684\u63d0\u793a\u6a21\u7248\uff0c\u4f60\u53ef\u4ee5\u5feb\u901f\u5efa\u7acb\u81ea\u5df1\u7684\u5927\u6a21\u578b\u5e94\u7528\uff0c\u800c\u4e0d\u9700\u8981\u82b1\u65f6\u95f4\u53bb\u8bbe\u8ba1\u548c\u6784\u9020\u63d0\u793a\u3002\n", "\n", "\u6700\u540e\uff0c\u6211\u4eec\u5728\u5efa\u7acb\u5927\u6a21\u578b\u5e94\u7528\u65f6\uff0c\u901a\u5e38\u5e0c\u671b\u6a21\u578b\u7684\u8f93\u51fa\u4e3a\u7ed9\u5b9a\u7684\u683c\u5f0f\uff0c\u6bd4\u5982\u5728\u8f93\u51fa\u4f7f\u7528\u7279\u5b9a\u7684\u5173\u952e\u8bcd\u6765\u8ba9\u8f93\u51fa\u7ed3\u6784\u5316\u3002 \u4e0b\u9762\u4e3a\u4e00\u4e2a\u4f7f\u7528\u5927\u6a21\u578b\u8fdb\u884c\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u4f8b\u5b50\uff0c\u5bf9\u4e8e\u95ee\u9898\uff1a*What is the elevation range for the area that the eastern sector of the Colorado orogeny extends into?*\n", "\n", "\u901a\u8fc7\u4f7f\u7528LangChain\u5e93\u51fd\u6570\uff0c\u8f93\u51fa\u91c7\u7528\"Thought\"\uff08\u601d\u8003\uff09\u3001\"Action\"\uff08\u884c\u52a8\uff09\u3001\"Observation\"\uff08\u89c2\u5bdf\uff09\u4f5c\u4e3a\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u7684\u5173\u952e\u8bcd\uff0c\u8ba9\u8f93\u51fa\u7ed3\u6784\u5316\u3002\n", "\n", "```\n", "Thought: I need to search Colorado orogeny, find the area that the eastern sector of the Colorado orogeny extends into, then find the elevation range of the area.\n", "Action: Search[Colorado orogeny]\n", "Observation: The Colorado orogeny was an episode of mountain building (an orogeny) in Colorado and surrounding areas.\n", "\n", "Thought: It does not mention the eastern sector. So I need to look up eastern sector.\n", "Action: Lookup[eastern sector]\n", "Observation: (Result 1 / 1) The eastern sector extends into the High Plains and is called the Central Plains orogeny.\n", "\n", "Thought: The eastern sector of Colorado orogeny extends into the High Plains. So I need to search High Plains and find its elevation range.\n", "Action: Search[High Plains]\n", "Observation: High Plains refers to one of two distinct land regions\n", "\n", "Thought: I need to instead search High Plains (United States).\n", "Action: Search[High Plains (United States)]\n", "Observation: The High Plains are a subregion of the Great Plains. From east to west, the High Plains rise in elevation from around 1,800 to 7,000 ft (550 to 2,130 m).[3]\n", "\n", "Thought: High Plains rise in elevation from around 1,800 to 7,000 ft, so the answer is 1,800 to 7,000 ft.\n", "Action: Finish[1,800 to 7,000 ft]\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\u5728\u8865\u5145\u6750\u6599\u4e2d\uff0c\u53ef\u4ee5\u67e5\u770b\u4f7f\u7528LangChain\u548cOpenAI\u8fdb\u884c\u94fe\u5f0f\u601d\u8003\u63a8\u7406\u7684\u53e6\u4e00\u4e2a\u4ee3\u7801\u5b9e\u4f8b\u3002"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 3.3 \u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.1 \u5982\u679c\u6ca1\u6709\u8f93\u51fa\u89e3\u6790\u5668\n", "\n", "\u5bf9\u4e8e\u7ed9\u5b9a\u7684\u8bc4\u4ef7`customer_review`, \u6211\u4eec\u5e0c\u671b\u63d0\u53d6\u4fe1\u606f\uff0c\u5e76\u6309\u4ee5\u4e0b\u683c\u5f0f\u8f93\u51fa\uff1a\n", "\n", "```python\n", "{\n", " \"gift\": False,\n", " \"delivery_days\": 5,\n", " \"price_value\": \"pretty affordable!\"\n", "}\n", "```"]}, {"cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": ["customer_review = \"\"\"\\\n", "This leaf blower is pretty amazing. It has four settings:\\\n", "candle blower, gentle breeze, windy city, and tornado. \\\n", "It arrived in two days, just in time for my wife's \\\n", "anniversary present. \\\n", "I think my wife liked it so much she was speechless. \\\n", "So far I've been the only one using it, and I've been \\\n", "using it every other morning to clear the leaves on our lawn. \\\n", "It's slightly more expensive than the other leaf blowers \\\n", "out there, but I think it's worth it for the extra features.\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32"]}, {"cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": ["review_template = \"\"\"\\\n", "For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? \\\n", "Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the product \\\n", "to arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,\\\n", "and output them as a comma separated Python list.\n", "\n", "Format the output as JSON with the following keys:\n", "gift\n", "delivery_days\n", "price_value\n", "\n", "text: {text}\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020langchain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['text'] output_parser=None partial_variables={} messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], output_parser=None, partial_variables={}, template='For the following text, extract the following information:\\n\\ngift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\\n\\ndelivery_days: How many days did it take for the product to arrive? If this information is not found, output -1.\\n\\nprice_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\\n\\nFormat the output as JSON with the following keys:\\ngift\\ndelivery_days\\nprice_value\\n\\ntext: {text}\\n', template_format='f-string', validate_template=True), additional_kwargs={})]\n"]}], "source": ["from langchain.prompts import ChatPromptTemplate\n", "prompt_template = ChatPromptTemplate.from_template(review_template)\n", "print(prompt_template)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u63d0\u793a\u6d88\u606f"]}, {"cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": ["messages = prompt_template.format_messages(text=customer_review)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u63d0\u53d6\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{\n", " \"gift\": false,\n", " \"delivery_days\": 2,\n", " \"price_value\": [\"It's slightly more expensive than the other leaf blowers out there, but I think it's worth it for the extra features.\"]\n", "}\n"]}], "source": ["chat = ChatOpenAI(temperature=0.0)\n", "response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udcdd \u5206\u6790\u4e0e\u603b\u7ed3\n", "`response.content`\u7c7b\u578b\u4e3a\u5b57\u7b26\u4e32\uff08`str`\uff09\uff0c\u800c\u5e76\u975e\u5b57\u5178(`dict`), \u76f4\u63a5\u4f7f\u7528`get`\u65b9\u6cd5\u4f1a\u62a5\u9519\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u9700\u8981\u8f93\u51fa\u89e3\u91ca\u5668\u3002"]}, {"cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [{"data": {"text/plain": ["str"]}, "execution_count": 44, "metadata": {}, "output_type": "execute_result"}], "source": ["type(response.content)"]}, {"cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [{"ename": "AttributeError", "evalue": "'str' object has no attribute 'get'", "output_type": "error", "traceback": ["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "Input \u001b[0;32mIn [45]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcontent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgift\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", "\u001b[0;31mAttributeError\u001b[0m: 'str' object has no attribute 'get'"]}], "source": ["response.content.get('gift')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.2 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["input_variables=['text'] output_parser=None partial_variables={} messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['text'], output_parser=None, partial_variables={}, template='\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\\n\\n\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\\n\\n\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\\n\\n\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\\n\\n\u4f7f\u7528\u4ee5\u4e0b\u952e\u5c06\u8f93\u51fa\u683c\u5f0f\u5316\u4e3a JSON\uff1a\\n\u793c\u7269\\n\u4ea4\u8d27\u5929\u6570\\n\u4ef7\u94b1\\n\\n\u6587\u672c: {text}\\n', template_format='f-string', validate_template=True), additional_kwargs={})]\n"]}], "source": ["from langchain.prompts import ChatPromptTemplate\n", "\n", "customer_review = \"\"\"\\\n", "\u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\\\n", "\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \\\n", "\u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\\\n", "\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \\\n", "\u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \\\n", "\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\\\n", "\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \\\n", "\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\\\n", "\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\"\"\"\n", "\n", "review_template = \"\"\"\\\n", "\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\n", "\n", "\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \\\n", "\u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\n", "\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\\\n", "\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\n", "\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\\\n", "\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\n", "\n", "\u4f7f\u7528\u4ee5\u4e0b\u952e\u5c06\u8f93\u51fa\u683c\u5f0f\u5316\u4e3a JSON\uff1a\n", "\u793c\u7269\n", "\u4ea4\u8d27\u5929\u6570\n", "\u4ef7\u94b1\n", "\n", "\u6587\u672c: {text}\n", "\"\"\"\n", "\n", "prompt_template = ChatPromptTemplate.from_template(review_template)\n", "print(prompt_template)\n"]}, {"cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{\n", " \"\u793c\u7269\": \"\u662f\u7684\",\n", " \"\u4ea4\u8d27\u5929\u6570\": 2,\n", " \"\u4ef7\u94b1\": [\"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"]\n", "}\n"]}], "source": ["messages = prompt_template.format_messages(text=customer_review)\n", "\n", "chat = ChatOpenAI(temperature=0.0)\n", "response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.3 LangChain\u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 1\ufe0f\u20e3 \u6784\u9020\u63d0\u793a\u6a21\u7248\u5b57\u7b26\u4e32"]}, {"cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": ["review_template_2 = \"\"\"\\\n", "For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? \\\n", "Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the product\\\n", "to arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,\\\n", "and output them as a comma separated Python list.\n", "\n", "text: {text}\n", "\n", "{format_instructions}\n", "\"\"\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 2\ufe0f\u20e3 \u6784\u9020langchain\u63d0\u793a\u6a21\u7248"]}, {"cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": ["prompt = ChatPromptTemplate.from_template(template=review_template_2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udd25 \u6784\u9020\u8f93\u51fa\u89e3\u6790\u5668"]}, {"cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"gift\": string // Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\t\"delivery_days\": string // How many days did it take for the product to arrive? If this information is not found, output -1.\n", "\t\"price_value\": string // Extract any sentences about the value or price, and output them as a comma separated Python list.\n", "}\n", "```\n"]}], "source": ["from langchain.output_parsers import ResponseSchema\n", "from langchain.output_parsers import StructuredOutputParser\n", "\n", "gift_schema = ResponseSchema(name=\"gift\",\n", " description=\"Was the item purchased\\\n", " as a gift for someone else? \\\n", " Answer True if yes,\\\n", " False if not or unknown.\")\n", "\n", "delivery_days_schema = ResponseSchema(name=\"delivery_days\",\n", " description=\"How many days\\\n", " did it take for the product\\\n", " to arrive? If this \\\n", " information is not found,\\\n", " output -1.\")\n", "\n", "price_value_schema = ResponseSchema(name=\"price_value\",\n", " description=\"Extract any\\\n", " sentences about the value or \\\n", " price, and output them as a \\\n", " comma separated Python list.\")\n", "\n", "\n", "response_schemas = [gift_schema, \n", " delivery_days_schema,\n", " price_value_schema]\n", "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)\n", "format_instructions = output_parser.get_format_instructions()\n", "print(format_instructions)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 3\ufe0f\u20e3 \u4f7f\u7528\u6a21\u7248\u5f97\u5230\u63d0\u793a\u6d88\u606f"]}, {"cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": ["messages = prompt.format_messages(text=customer_review, format_instructions=format_instructions)"]}, {"cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the productto arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\n", "\n", "text: \u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\n", "\n", "The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"gift\": string // Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\t\"delivery_days\": string // How many days did it take for the product to arrive? If this information is not found, output -1.\n", "\t\"price_value\": string // Extract any sentences about the value or price, and output them as a comma separated Python list.\n", "}\n", "```\n", "\n"]}], "source": ["print(messages[0].content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 4\ufe0f\u20e3 \u8c03\u7528chat\u6a21\u578b\u63d0\u53d6\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["```json\n", "{\n", "\t\"gift\": false,\n", "\t\"delivery_days\": \"2\",\n", "\t\"price_value\": \"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"\n", "}\n", "```\n"]}], "source": ["response = chat(messages)\n", "print(response.content)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### 5\ufe0f\u20e3 \u4f7f\u7528\u8f93\u51fa\u89e3\u6790\u5668\u89e3\u6790\u8f93\u51fa"]}, {"cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [{"data": {"text/plain": ["{'gift': False, 'delivery_days': '2', 'price_value': '\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9'}"]}, "execution_count": 54, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict = output_parser.parse(response.content)\n", "output_dict"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##### \ud83d\udcdd \u5206\u6790\u4e0e\u603b\u7ed3\n", "`output_dict`\u7c7b\u578b\u4e3a\u5b57\u5178(`dict`), \u53ef\u76f4\u63a5\u4f7f\u7528`get`\u65b9\u6cd5\u3002\u8fd9\u6837\u7684\u8f93\u51fa\u66f4\u65b9\u4fbf\u4e0b\u6e38\u4efb\u52a1\u7684\u5904\u7406\u3002"]}, {"cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [{"data": {"text/plain": ["dict"]}, "execution_count": 55, "metadata": {}, "output_type": "execute_result"}], "source": ["type(output_dict)"]}, {"cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [{"data": {"text/plain": ["'2'"]}, "execution_count": 56, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict.get('delivery_days')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### 3.3.4 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"\u793c\u7269\": string // \u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\t\"\u4ea4\u8d27\u5929\u6570\": string // \u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\t\"\u4ef7\u94b1\": string // \u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\n", "}\n", "```\n"]}], "source": ["# \u4e2d\u6587\n", "review_template_2 = \"\"\"\\\n", "\u5bf9\u4e8e\u4ee5\u4e0b\u6587\u672c\uff0c\u8bf7\u4ece\u4e2d\u63d0\u53d6\u4ee5\u4e0b\u4fe1\u606f\uff1a\uff1a\n", "\n", "\u793c\u7269\uff1a\u8be5\u5546\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f\n", "\u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff1b\u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\n", "\u4ea4\u8d27\u5929\u6570\uff1a\u4ea7\u54c1\u5230\u8fbe\u9700\u8981\u591a\u5c11\u5929\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\n", "\u4ef7\u94b1\uff1a\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\u3002\n", "\n", "\u6587\u672c: {text}\n", "\n", "{format_instructions}\n", "\"\"\"\n", "\n", "from langchain.output_parsers import ResponseSchema\n", "from langchain.output_parsers import StructuredOutputParser\n", "\n", "gift_schema = ResponseSchema(name=\"\u793c\u7269\",\n", " description=\"\u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f\\\n", " \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c\\\n", " \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\")\n", "\n", "delivery_days_schema = ResponseSchema(name=\"\u4ea4\u8d27\u5929\u6570\",\n", " description=\"\u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f\\\n", " \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\")\n", "\n", "price_value_schema = ResponseSchema(name=\"\u4ef7\u94b1\",\n", " description=\"\u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c\\\n", " \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\")\n", "\n", "\n", "response_schemas = [gift_schema, \n", " delivery_days_schema,\n", " price_value_schema]\n", "output_parser = StructuredOutputParser.from_response_schemas(response_schemas)\n", "format_instructions = output_parser.get_format_instructions()\n", "print(format_instructions)"]}, {"cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["For the following text, extract the following information:\n", "\n", "gift: Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.\n", "\n", "delivery_days: How many days did it take for the productto arrive? If this information is not found, output -1.\n", "\n", "price_value: Extract any sentences about the value or price,and output them as a comma separated Python list.\n", "\n", "text: \u8fd9\u6b3e\u5439\u53f6\u673a\u975e\u5e38\u795e\u5947\u3002 \u5b83\u6709\u56db\u4e2a\u8bbe\u7f6e\uff1a\u5439\u8721\u70db\u3001\u5fae\u98ce\u3001\u98ce\u57ce\u3001\u9f99\u5377\u98ce\u3002 \u4e24\u5929\u540e\u5c31\u5230\u4e86\uff0c\u6b63\u597d\u8d76\u4e0a\u6211\u59bb\u5b50\u7684\u5468\u5e74\u7eaa\u5ff5\u793c\u7269\u3002 \u6211\u60f3\u6211\u7684\u59bb\u5b50\u4f1a\u559c\u6b22\u5b83\u5230\u8bf4\u4e0d\u51fa\u8bdd\u6765\u3002 \u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u662f\u552f\u4e00\u4e00\u4e2a\u4f7f\u7528\u5b83\u7684\u4eba\uff0c\u800c\u4e14\u6211\u4e00\u76f4\u6bcf\u9694\u4e00\u5929\u65e9\u4e0a\u7528\u5b83\u6765\u6e05\u7406\u8349\u576a\u4e0a\u7684\u53f6\u5b50\u3002 \u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\uff0c\u4f46\u6211\u8ba4\u4e3a\u5b83\u7684\u989d\u5916\u529f\u80fd\u662f\u503c\u5f97\u7684\u3002\n", "\n", "\n", "The output should be a markdown code snippet formatted in the following schema, including the leading and trailing \"```json\" and \"```\":\n", "\n", "```json\n", "{\n", "\t\"\u793c\u7269\": string // \u8fd9\u4ef6\u7269\u54c1\u662f\u4f5c\u4e3a\u793c\u7269\u9001\u7ed9\u522b\u4eba\u7684\u5417\uff1f \u5982\u679c\u662f\uff0c\u5219\u56de\u7b54 \u662f\u7684\uff0c \u5982\u679c\u5426\u6216\u672a\u77e5\uff0c\u5219\u56de\u7b54 \u4e0d\u662f\u3002\n", "\t\"\u4ea4\u8d27\u5929\u6570\": string // \u4ea7\u54c1\u9700\u8981\u591a\u5c11\u5929\u624d\u80fd\u5230\u8fbe\uff1f \u5982\u679c\u6ca1\u6709\u627e\u5230\u8be5\u4fe1\u606f\uff0c\u5219\u8f93\u51fa-1\u3002\n", "\t\"\u4ef7\u94b1\": string // \u63d0\u53d6\u6709\u5173\u4ef7\u503c\u6216\u4ef7\u683c\u7684\u4efb\u4f55\u53e5\u5b50\uff0c \u5e76\u5c06\u5b83\u4eec\u8f93\u51fa\u4e3a\u9017\u53f7\u5206\u9694\u7684 Python \u5217\u8868\n", "}\n", "```\n", "\n"]}], "source": ["messages = prompt.format_messages(text=customer_review, format_instructions=format_instructions)\n", "print(messages[0].content)"]}, {"cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["```json\n", "{\n", "\t\"\u793c\u7269\": false,\n", "\t\"\u4ea4\u8d27\u5929\u6570\": \"\u4e24\u5929\u540e\",\n", "\t\"\u4ef7\u94b1\": \"\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9\"\n", "}\n", "```\n"]}], "source": ["response = chat(messages)\n", "print(response.content)\n"]}, {"cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [{"data": {"text/plain": ["{'\u793c\u7269': False, '\u4ea4\u8d27\u5929\u6570': '\u4e24\u5929\u540e', '\u4ef7\u94b1': '\u5b83\u6bd4\u5176\u4ed6\u5439\u53f6\u673a\u7a0d\u5fae\u8d35\u4e00\u70b9'}"]}, "execution_count": 60, "metadata": {}, "output_type": "execute_result"}], "source": ["output_dict = output_parser.parse(response.content)\n", "output_dict"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## \u56db\u3001\u8865\u5145\u6750\u6599"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### 4.1 \u94fe\u5f0f\u601d\u8003\u63a8\u7406(ReAct)\n", "\u53c2\u8003\u8d44\u6599\uff1a[ReAct (Reason+Act) prompting in OpenAI GPT and LangChain](https://tsmatz.wordpress.com/2023/03/07/react-with-openai-gpt-and-langchain/)"]}, {"cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [], "source": ["!pip install -q wikipedia"]}, {"cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "\u001b[32;1m\u001b[1;3mThought: I need to search David Chanoff and find the U.S. Navy admiral he collaborated with. Then I need to find the president under whom the admiral served as the ambassador to the United Kingdom.\n", "Action: Search[David Chanoff]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, \u0110o\u00e0n V\u0103n To\u1ea1i, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mDavid Chanoff has collaborated with several individuals, including Augustus A. White, Joycelyn Elders, \u0110o\u00e0n V\u0103n To\u1ea1i, William J. Crowe, Ariel Sharon, Kenneth Good, and Felix Zandman. I need to search each of these individuals to find the U.S. Navy admiral. \n", "Action: Search[Augustus A. White]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mAugustus A. White III (born June 4, 1936) is the Ellen and Melvin Gordon Distinguished Professor of Medical Education and Professor of Orthopedic Surgery at Harvard Medical School and a former Orthopaedic Surgeon-in-Chief at Beth Israel Hospital, Boston, Massachusetts. White was the first African American medical student at Stanford, surgical resident at Yale University, professor of medicine at Yale, and department head at a Harvard-affiliated hospital (Beth Israel Hospital).\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mAugustus A. White III is not a U.S. Navy admiral. I need to search the next individual, Joycelyn Elders.\n", "Action: Search[Joycelyn Elders]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mMinnie Joycelyn Elders (born Minnie Lee Jones; August 13, 1933) is an American pediatrician and public health administrator who served as Surgeon General of the United States from 1993 to 1994. A vice admiral in the Public Health Service Commissioned Corps, she was the second woman, second person of color, and first African American to serve as Surgeon General. \n", "Elders is best known for her frank discussion of her views on controversial issues such as drug legalization, masturbation, and distributing contraception in schools. She was forced to resign in December 1994 amidst controversy as a result of her views. She is currently a professor emerita of pediatrics at the University of Arkansas for Medical Sciences.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mJoycelyn Elders is a pediatrician and public health administrator, not a U.S. Navy admiral. I need to search the next individual, \u0110o\u00e0n V\u0103n To\u1ea1i.\n", "Action: Search[\u0110o\u00e0n V\u0103n To\u1ea1i]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3m\u0110o\u00e0n V\u0103n To\u1ea1i (1945 in Vietnam \u2013 November 2017 in California) was a Vietnamese-born naturalized American activist and the author of The Vietnamese Gulag (Simon & Schuster, 1986).\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3m\u0110o\u00e0n V\u0103n To\u1ea1i is an activist and author, not a U.S. Navy admiral. I need to search the next individual, William J. Crowe.\n", "Action: Search[William J. Crowe]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mWilliam James Crowe Jr. (January 2, 1925 \u2013 October 18, 2007) was a United States Navy admiral and diplomat who served as the 11th chairman of the Joint Chiefs of Staff under Presidents Ronald Reagan and George H. W. Bush, and as the ambassador to the United Kingdom and Chair of the Intelligence Oversight Board under President Bill Clinton.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mWilliam J. Crowe is a U.S. Navy admiral and diplomat. I need to find the president under whom he served as the ambassador to the United Kingdom.\n", "Action: Search[William J. Crowe ambassador to United Kingdom]\u001b[0m\n", "Observation: \u001b[36;1m\u001b[1;3mWilliam James Crowe Jr. (January 2, 1925 \u2013 October 18, 2007) was a United States Navy admiral and diplomat who served as the 11th chairman of the Joint Chiefs of Staff under Presidents Ronald Reagan and George H. W. Bush, and as the ambassador to the United Kingdom and Chair of the Intelligence Oversight Board under President Bill Clinton.\u001b[0m\n", "Thought:\u001b[32;1m\u001b[1;3mWilliam J. Crowe served as the ambassador to the United Kingdom under President Bill Clinton. So the answer is Bill Clinton.\n", "Action: Finish[Bill Clinton]\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Bill Clinton'"]}, "execution_count": 69, "metadata": {}, "output_type": "execute_result"}], "source": ["from langchain.docstore.wikipedia import Wikipedia\n", "from langchain.llms import OpenAI\n", "from langchain.agents import initialize_agent, Tool, AgentExecutor\n", "from langchain.agents.react.base import DocstoreExplorer\n", "\n", "docstore=DocstoreExplorer(Wikipedia())\n", "tools = [\n", " Tool(\n", " name=\"Search\",\n", " func=docstore.search,\n", " description=\"Search for a term in the docstore.\",\n", " ),\n", " Tool(\n", " name=\"Lookup\",\n", " func=docstore.lookup,\n", " description=\"Lookup a term in the docstore.\",\n", " )\n", "]\n", "\n", "# \u4f7f\u7528\u5927\u8bed\u8a00\u6a21\u578b\n", "llm = OpenAI(\n", " model_name=\"gpt-3.5-turbo\",\n", " temperature=0,\n", ")\n", "\n", "# \u521d\u59cb\u5316ReAct\u4ee3\u7406\n", "react = initialize_agent(tools, llm, agent=\"react-docstore\", verbose=True)\n", "agent_executor = AgentExecutor.from_agent_and_tools(\n", " agent=react.agent,\n", " tools=tools,\n", " verbose=True,\n", ")\n", "\n", "\n", "question = \"Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?\"\n", "agent_executor.run(question)"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/content/LangChain for LLM Application Development/3.储存 Memory.ipynb b/content/LangChain for LLM Application Development/3.储存 Memory.ipynb index 06d63e7..2d8fe64 100644 --- a/content/LangChain for LLM Application Development/3.储存 Memory.ipynb +++ b/content/LangChain for LLM Application Development/3.储存 Memory.ipynb @@ -1,1697 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "a786c77c", - "metadata": { - "tags": [] - }, - "source": [ - "# 第三章 储存\n", - "\n", - " - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n", - " - [二、对话缓存储存 ](#二、对话缓存储存--)\n", - " - [2.1 开始对话,第一轮](#2.1-开始对话,第一轮)\n", - " - [2.2 第二轮对话](#2.2-第二轮对话)\n", - " - [2.3 第三轮对话](#2.3-第三轮对话)\n", - " - [2.4 .memory.buffer储存了当前为止所有的对话信息](#2.4-.memory.buffer储存了当前为止所有的对话信息)\n", - " - [2.5 也可以通过memory.load_memory_variables({})打印历史消息](#2.5-也可以通过memory.load_memory_variables({})打印历史消息)\n", - " - [2.6 添加指定的输入输出内容到记忆缓存区](#2.6-添加指定的输入输出内容到记忆缓存区)\n", - " - [三、对话缓存窗口储存](#三、对话缓存窗口储存)\n", - " - [3.1 向memory添加两轮对话,并查看记忆变量当前的记录](#3.1-向memory添加两轮对话,并查看记忆变量当前的记录)\n", - " - [3.2 在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆](#3.2-在看一个例子,发现和上面的结果一样,只保留了一轮对话记忆)\n", - " - [3.3 将对话缓存窗口记忆应用到对话链中](#3.3-将对话缓存窗口记忆应用到对话链中)\n", - " - [四、对话token缓存储存](#四、对话token缓存储存)\n", - " - [4.1 导入相关包和API密钥](#4.1-导入相关包和API密钥)\n", - " - [4.2 限制token数量,进行测试](#4.2-限制token数量,进行测试)\n", - " - [4.3 中文例子](#4.3-中文例子)\n", - " - [五、对话摘要缓存储存](#五、对话摘要缓存储存)\n", - " - [5.1 创建一个长字符串,其中包含某人的日程安排](#5.1-创建一个长字符串,其中包含某人的日程安排)\n", - " - [5.2 基于上面的memory,新建一个对话链](#5.2-基于上面的memory,新建一个对话链)\n", - " - [5.3 中文例子](#5.3-中文例子)\n" - ] - }, - { - "cell_type": "markdown", - "id": "7e10db6f", - "metadata": {}, - "source": [ - "当你与那些语言模型进行交互的时候,他们不会记得你之前和他进行的交流内容,这在我们构建一些应用程序(如聊天机器人)的时候,是一个很大的问题 -- 显得不够智能!因此,在本节中我们将介绍 LangChain 中的储存模块,即如何将先前的对话嵌入到语言模型中的,使其具有连续对话的能力。\n", - "\n", - "当使用 LangChain 中的储存(Memory)模块时,它可以帮助保存和管理历史聊天消息,以及构建关于特定实体的知识。这些组件可以跨多轮对话储存信息,并允许在对话期间跟踪特定信息和上下文。\n", - "\n", - "LangChain 提供了多种储存类型。其中,缓冲区储存允许保留最近的聊天消息,摘要储存则提供了对整个对话的摘要。实体储存 则允许在多轮对话中保留有关特定实体的信息。这些记忆组件都是模块化的,可与其他组件组合使用,从而增强机器人的对话管理能力。储存模块可以通过简单的API调用来访问和更新,允许开发人员更轻松地实现对话历史记录的管理和维护。\n", - "\n", - "此次课程主要介绍其中四种储存模块,其他模块可查看文档学习。\n", - "- 对话缓存储存 (ConversationBufferMemory)\n", - "- 对话缓存窗口储存 (ConversationBufferWindowMemory)\n", - "- 对话令牌缓存储存 (ConversationTokenBufferMemory)\n", - "- 对话摘要缓存储存 (ConversationSummaryBufferMemory)\n", - "\n", - "在LangChain中,储存 指的是大语言模型(LLM)的短期记忆。为什么是短期记忆?那是因为LLM训练好之后 (获得了一些长期记忆),它的参数便不会因为用户的输入而发生改变。当用户与训练好的LLM进行对话时,LLM会暂时记住用户的输入和它已经生成的输出,以便预测之后的输出,而模型输出完毕后,它便会“遗忘”之前用户的输入和它的输出。因此,之前的这些信息只能称作为LLM的短期记忆。 \n", - " \n", - "为了延长LLM短期记忆的保留时间,则需要借助一些外部储存方式来进行记忆,以便在用户与LLM对话中,LLM能够尽可能的知道用户与它所进行的历史对话信息。 " - ] - }, - { - "cell_type": "markdown", - "id": "1ca56e6b-1e07-4405-a1ca-f4237f20fa75", - "metadata": { - "jp-MarkdownHeadingCollapsed": true, - "tags": [] - }, - "source": [ - "## 一、设置OpenAI API Key\n", - "\n", - "登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n", - "\n", - "- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n", - "- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n", - "\n", - "

\n", - " OPENAI_API_KEY=\"your_api_key\" \n", - "

\n", - " \n", - " 替换\"your_api_key\"为你自己的 API Key" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6932bd47-c6d5-4794-8102-a12b84412a93", - "metadata": {}, - "outputs": [], - "source": [ - "# 下载需要的包python-dotenv和openai\n", - "# 如果你需要查看安装过程日志,可删除 -q\n", - "!pip install -q python-dotenv\n", - "!pip install -q openai" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "10446712-9fa6-4d71-94ce-2ea4cf197e54", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "\n", - "import openai\n", - "from dotenv import find_dotenv, load_dotenv\n", - "\n", - "# 读取本地/项目的环境变量。\n", - "\n", - "# find_dotenv()寻找并定位.env文件的路径\n", - "# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中\n", - "# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n", - "_ = load_dotenv(find_dotenv())\n", - "\n", - "# 获取环境变量 OPENAI_API_KEY\n", - "openai.api_key = os.environ[\"OPENAI_API_KEY\"]" - ] - }, - { - "cell_type": "markdown", - "id": "1297dcd5", - "metadata": { - "tags": [] - }, - "source": [ - "## 二、对话缓存储存\n", - " " - ] - }, - { - "cell_type": "markdown", - "id": "ffa8cd26-45c5-4bae-90b2-b07d23bf3bb2", - "metadata": {}, - "source": [ - "### 2.1 英文版" - ] - }, - { - "cell_type": "markdown", - "id": "b7e77a3d-7aaa-48c1-b219-19bd6f4eb674", - "metadata": { - "tags": [] - }, - "source": [ - "#### 2.1.1 初始化对话模型" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "id": "20ad6fe2", - "metadata": { - "height": 98 - }, - "outputs": [], - "source": [ - "from langchain.chains import ConversationChain\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.memory import ConversationBufferMemory" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "id": "88bdf13d", - "metadata": { - "height": 133 - }, - "outputs": [], - "source": [ - "# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。\n", - "# 如果你想要每次得到不一样的有新意的答案,可以尝试增大该参数。\n", - "llm = ChatOpenAI(temperature=0.0) \n", - "\n", - "memory = ConversationBufferMemory()\n", - "\n", - "# 新建一个 ConversationChain Class 实例\n", - "# verbose参数设置为True时,程序会输出更详细的信息,以提供更多的调试或运行时信息。\n", - "# 相反,当将verbose参数设置为False时,程序会以更简洁的方式运行,只输出关键的信息。\n", - "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )" - ] - }, - { - "cell_type": "markdown", - "id": "dea83837", - "metadata": { - "tags": [] - }, - "source": [ - "#### 2.1.2 第一轮对话" - ] - }, - { - "cell_type": "markdown", - "id": "1a3b4c42", - "metadata": {}, - "source": [ - "当我们运行预测(predict)时,生成了一些提示,如下所见,他说“以下是人类和AI之间友好的对话,AI健谈“等等,这实际上是LangChain生成的提示,以使系统进行希望和友好的对话,并且必须保存对话,并提示了当前已完成的模型链。" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "db24677d", - "metadata": { - "height": 47 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "\n", - "Human: Hi, my name is Andrew\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "\"Hello Andrew! It's nice to meet you. How can I assist you today?\"" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"Hi, my name is Andrew\")" - ] - }, - { - "cell_type": "markdown", - "id": "e71564ad", - "metadata": {}, - "source": [ - "#### 2.1.3 第二轮对话" - ] - }, - { - "cell_type": "markdown", - "id": "54d006bd", - "metadata": {}, - "source": [ - "当我们进行第二轮对话时,它会保留上面的提示" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "id": "cc3ef937", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "Human: Hi, my name is Andrew\n", - "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", - "Human: What is 1+1?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'1+1 is equal to 2.'" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"What is 1+1?\")" - ] - }, - { - "cell_type": "markdown", - "id": "33cb734b", - "metadata": {}, - "source": [ - "#### 2.1.4 第三轮对话" - ] - }, - { - "cell_type": "markdown", - "id": "0393df3d", - "metadata": {}, - "source": [ - "为了验证他是否记忆了前面的对话内容,我们让他回答前面已经说过的内容(我的名字),可以看到他确实输出了正确的名字,因此这个对话链随着往下进行会越来越长" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "id": "acf3339a", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "Human: Hi, my name is Andrew\n", - "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", - "Human: What is 1+1?\n", - "AI: 1+1 is equal to 2.\n", - "Human: What is my name?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'Your name is Andrew.'" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"What is my name?\")" - ] - }, - { - "cell_type": "markdown", - "id": "5a96a8d9", - "metadata": {}, - "source": [ - "#### 2.1.5 查看储存缓存\n", - "\n", - "储存缓存(memory.buffer)\n", - "储存了当前为止所有的对话信息" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "id": "2529400d", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Human: Hi, my name is Andrew\n", - "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", - "Human: What is 1+1?\n", - "AI: 1+1 is equal to 2.\n", - "Human: What is my name?\n", - "AI: Your name is Andrew.\n" - ] - } - ], - "source": [ - "print(memory.buffer) " - ] - }, - { - "cell_type": "markdown", - "id": "0b5de846", - "metadata": {}, - "source": [ - "也可以通过memory.load_memory_variables({})打印缓存中的历史消息。这里的`{}`是一个空字典,有一些更高级的功能,使用户可以使用更复杂的输入,但我们不会在这个短期课程中讨论它们,所以不要担心为什么这里有一个空的花括号。" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "id": "5018cb0a", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'history': \"Human: Hi, my name is Andrew\\nAI: Hello Andrew! It's nice to meet you. How can I assist you today?\\nHuman: What is 1+1?\\nAI: 1+1 is equal to 2.\\nHuman: What is my name?\\nAI: Your name is Andrew.\"}\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({}))" - ] - }, - { - "cell_type": "markdown", - "id": "07d2e892", - "metadata": {}, - "source": [ - "#### 2.1.6 直接添加内容到储存缓存" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "id": "14219b70", - "metadata": { - "height": 31 - }, - "outputs": [], - "source": [ - "memory = ConversationBufferMemory() # 新建一个空的对话缓存记忆" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "id": "a36e9905", - "metadata": { - "height": 48 - }, - "outputs": [], - "source": [ - "memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"}) # 向缓存区添加指定对话的输入输出" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "id": "61631b1f", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Human: Hi\n", - "AI: What's up\n" - ] - } - ], - "source": [ - "print(memory.buffer) # 查看缓存区结果" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "id": "a2fdf9ec", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'history': \"Human: Hi\\nAI: What's up\"}\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({}))# 再次加载记忆变量" - ] - }, - { - "cell_type": "markdown", - "id": "2ac544f2", - "metadata": {}, - "source": [ - "继续添加新的内容,对话历史都保存下来在了!" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "id": "7ca79256", - "metadata": { - "height": 64 - }, - "outputs": [], - "source": [ - "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "id": "890a4497", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': \"Human: Hi\\nAI: What's up\\nHuman: Not much, just hanging\\nAI: Cool\"}" - ] - }, - "execution_count": 59, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "6eddd91a-bf1c-4b82-b99c-c585420e4ecb", - "metadata": {}, - "source": [ - "### 2.2 中文版" - ] - }, - { - "cell_type": "markdown", - "id": "55b3e4e9-7a6a-4a09-9ac3-0096a67849c7", - "metadata": {}, - "source": [ - "#### 2.1.1 初始化对话模型" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "3577aaff-7edb-40b0-866a-e407e63d55e0", - "metadata": { - "height": 98 - }, - "outputs": [], - "source": [ - "from langchain.chains import ConversationChain\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.memory import ConversationBufferMemory" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "a77d37ab-1f75-4ae8-8d7c-5066773ead81", - "metadata": { - "height": 133 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "\n", - "Human: 你好, 我叫皮皮鲁\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?'" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "llm = ChatOpenAI(temperature=0.0) \n", - "\n", - "memory = ConversationBufferMemory()\n", - "\n", - "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )" - ] - }, - { - "cell_type": "markdown", - "id": "747cb539-abc4-4e47-8cb9-1ee608ab07fc", - "metadata": {}, - "source": [ - "#### 2.1.2 第一轮对话" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "99e48462-7a92-4842-bdaa-2a478ba2252c", - "metadata": {}, - "outputs": [], - "source": [ - "conversation.predict(input=\"你好, 我叫皮皮鲁\")" - ] - }, - { - "cell_type": "markdown", - "id": "979d320b-6b20-4722-99db-c48a43711d6c", - "metadata": {}, - "source": [ - "#### 2.1.3 第二轮对话" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "6ed6e97a-d7ea-4188-a6d7-f91d2a29d14a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "Human: 你好, 我叫皮皮鲁\n", - "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", - "Human: 1+1等于多少?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'1+1等于2。'" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"1+1等于多少?\")" - ] - }, - { - "cell_type": "markdown", - "id": "8a1fd531-216e-42d8-b226-839747ad7dd3", - "metadata": {}, - "source": [ - "#### 2.1.4 第三轮对话" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b5dfe488-2758-42c7-9c20-e483b4c22ab8", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "Human: 你好, 我叫皮皮鲁\n", - "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", - "Human: 1+1等于多少?\n", - "AI: 1+1等于2。\n", - "Human: What is my name?\n", - "AI: 你的名字是皮皮鲁。\n", - "Human: 我叫什么名字?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'你叫皮皮鲁。'" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"我叫什么名字?\")" - ] - }, - { - "cell_type": "markdown", - "id": "05d9822e-943d-4905-a1f8-a0d28c215d60", - "metadata": {}, - "source": [ - "#### 2.1.5 查看储存缓存" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "0795580f-b6b6-47e0-8882-26fe204560bd", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Human: 你好, 我叫皮皮鲁\n", - "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", - "Human: 1+1等于多少?\n", - "AI: 1+1等于2。\n", - "Human: What is my name?\n", - "AI: 你的名字是皮皮鲁。\n", - "Human: 我叫什么名字?\n", - "AI: 你叫皮皮鲁。\n" - ] - } - ], - "source": [ - "print(memory.buffer) " - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "dfe7824f-bd6e-4b95-92e2-1c85c62a92e9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Human: 你好, 我叫皮皮鲁\n", - "AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", - "Human: 1+1等于多少?\n", - "AI: 1+1等于2。\n", - "Human: What is my name?\n", - "AI: 你的名字是皮皮鲁。\n", - "Human: 我叫什么名字?\n", - "AI: 你叫皮皮鲁。\n" - ] - } - ], - "source": [ - "print(memory.buffer) " - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "48942759-8afb-4aed-80c5-a48952a2b0c0", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'history': 'Human: 你好, 我叫皮皮鲁\\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\\nHuman: 1+1等于多少?\\nAI: 1+1等于2。\\nHuman: What is my name?\\nAI: 你的名字是皮皮鲁。\\nHuman: 我叫什么名字?\\nAI: 你叫皮皮鲁。'}\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({}))" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "4d0c4625-e928-45dc-b8da-4ab865ac5f7e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: 你好, 我叫皮皮鲁\\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\\nHuman: 1+1等于多少?\\nAI: 1+1等于2。\\nHuman: What is my name?\\nAI: 你的名字是皮皮鲁。\\nHuman: 我叫什么名字?\\nAI: 你叫皮皮鲁。'}" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "80f3778e-5fbf-43ed-9df1-d57d98ec6fb0", - "metadata": {}, - "source": [ - "#### 2.1.6 直接添加内容到储存缓存" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "147b2c30-1662-4b49-aaf8-c228428e5cc6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西'}" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory = ConversationBufferMemory()\n", - "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "6b5e27f0-dad7-41b6-9326-bebf6299638f", - "metadata": { - "height": 64 - }, - "outputs": [], - "source": [ - "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "id": "cfa7c555-06ab-4906-b3dc-906f789e08f5", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool'}" - ] - }, - "execution_count": 44, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "id": "deb33de8-37ea-4180-a73e-0fc456b14eb0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: 你好,我叫皮皮鲁\\nAI: 你好啊,我叫鲁西西\\nHuman: Not much, just hanging\\nAI: Cool\\nHuman: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "10146f1a-0114-4902-8122-d19ae6f7c461", - "metadata": {}, - "source": [ - "### 2.3 总结" - ] - }, - { - "cell_type": "markdown", - "id": "2759b6bc-edb2-4cfe-b0f8-1bf6c4d796f9", - "metadata": {}, - "source": [ - "当我们在使用大型语言模型进行聊天对话时,**大型语言模型本身实际上是无状态的。语言模型本身并不记得到目前为止的历史对话**。每次调用API结点都是独立的。储存(Memory)可以储存到目前为止的所有术语或对话,并将其输入或附加上下文到LLM中用于生成输出。如此看起来就好像它在进行下一轮对话的时候,记得之前说过什么。\n" - ] - }, - { - "cell_type": "markdown", - "id": "cf98e9ff", - "metadata": {}, - "source": [ - "## 三、对话缓存窗口储存\n", - " \n", - "随着对话变得越来越长,所需的内存量也变得非常长。将大量的tokens发送到LLM的成本,也会变得更加昂贵,这也就是为什么API的调用费用,通常是基于它需要处理的tokens数量而收费的。\n", - " \n", - "针对以上问题,LangChain也提供了几种方便的储存方式来保存历史对话。其中,对话缓存窗口储存只保留一个窗口大小的对话。它只使用最近的n次交互。这可以用于保持最近交互的滑动窗口,以便缓冲区不会过大" - ] - }, - { - "cell_type": "markdown", - "id": "b63c9061-9916-4524-b497-93a0aa2b7d06", - "metadata": {}, - "source": [ - "### 3.1 英文版" - ] - }, - { - "cell_type": "markdown", - "id": "641477a4", - "metadata": {}, - "source": [ - "#### 3.1.1 添加两轮对话到窗口储存" - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "id": "3ea6233e", - "metadata": { - "height": 47 - }, - "outputs": [], - "source": [ - "from langchain.memory import ConversationBufferWindowMemory\n", - "\n", - "# k 为窗口参数,k=1表明只保留一个对话记忆\n", - "memory = ConversationBufferWindowMemory(k=1) " - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "id": "dc4553fb", - "metadata": { - "height": 115 - }, - "outputs": [], - "source": [ - "# 向memory添加两轮对话\n", - "memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"})\n", - "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "id": "6a788403", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: Not much, just hanging\\nAI: Cool'}" - ] - }, - "execution_count": 67, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 并查看记忆变量当前的记录\n", - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "63bda148", - "metadata": {}, - "source": [ - "#### 3.1.2 在对话链中应用窗口储存" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "id": "4087bc87", - "metadata": { - "height": 133 - }, - "outputs": [], - "source": [ - "llm = ChatOpenAI(temperature=0.0)\n", - "memory = ConversationBufferWindowMemory(k=1)\n", - "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )" - ] - }, - { - "cell_type": "markdown", - "id": "b6d661e3", - "metadata": {}, - "source": [ - "注意此处!由于这里用的是一个窗口的记忆,因此只能保存一轮的历史消息,因此AI并不能知道你第一轮对话中提到的名字,他最多只能记住上一轮(第二轮)的对话信息" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "id": "4faaa952", - "metadata": { - "height": 47 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"Hello Andrew! It's nice to meet you. How can I assist you today?\"" - ] - }, - "execution_count": 69, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"Hi, my name is Andrew\")" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "id": "bb20ddaa", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "'1+1 is equal to 2.'" - ] - }, - "execution_count": 70, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"What is 1+1?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 71, - "id": "489b2194", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "\"I'm sorry, but I don't have access to personal information.\"" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"What is my name?\")" - ] - }, - { - "cell_type": "markdown", - "id": "88837e7c-cf4b-469e-b820-bbfc49ba876c", - "metadata": {}, - "source": [ - "### 3.2 中文版" - ] - }, - { - "cell_type": "markdown", - "id": "760ec3ad-6959-4a36-b1b5-4fcafe8088ad", - "metadata": {}, - "source": [ - "#### 3.1.1 添加两轮对话到窗口储存" - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "id": "68a2907c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'Human: 很高兴和你成为朋友!\\nAI: 是的,让我们一起去冒险吧!'}" - ] - }, - "execution_count": 72, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langchain.memory import ConversationBufferWindowMemory\n", - "\n", - "# k=1表明只保留一个对话记忆\n", - "memory = ConversationBufferWindowMemory(k=1) \n", - "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", - "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "dcabf017-5bfd-4904-9f06-388f994eddc9", - "metadata": {}, - "source": [ - "#### 3.1.2 在对话链中应用窗口储存" - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "id": "1ee854d9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\n", - "1+1等于2。\n", - "很抱歉,我无法知道您的名字。\n" - ] - } - ], - "source": [ - "llm = ChatOpenAI(temperature=0.0)\n", - "memory = ConversationBufferWindowMemory(k=1)\n", - "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )\n", - "print(conversation.predict(input=\"你好, 我叫皮皮鲁\"))\n", - "print(conversation.predict(input=\"1+1等于多少?\"))\n", - "print(conversation.predict(input=\"我叫什么名字?\"))" - ] - }, - { - "cell_type": "markdown", - "id": "d2931b92", - "metadata": {}, - "source": [ - "## 四、对话token缓存储存" - ] - }, - { - "cell_type": "markdown", - "id": "dff5b4c7", - "metadata": {}, - "source": [ - "使用对话token缓存记忆,内存将限制保存的token数量。如果token数量超出指定数目,它会切掉这个对话的早期部分\n", - "以保留与最近的交流相对应的token数量,但不超过token限制。" - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "id": "9f6d063c", - "metadata": { - "height": 31 - }, - "outputs": [], - "source": [ - "!pip install -q tiktoken " - ] - }, - { - "cell_type": "code", - "execution_count": 77, - "id": "fb9020ed", - "metadata": { - "height": 81 - }, - "outputs": [], - "source": [ - "from langchain.llms import OpenAI\n", - "from langchain.memory import ConversationTokenBufferMemory" - ] - }, - { - "cell_type": "markdown", - "id": "f3a84112", - "metadata": {}, - "source": [ - "### 4.1 英文版\n", - "添加对话到Token缓存储存,限制token数量,进行测试" - ] - }, - { - "cell_type": "code", - "execution_count": 78, - "id": "43582ee6", - "metadata": { - "height": 149 - }, - "outputs": [], - "source": [ - "memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", - "memory.save_context({\"input\": \"AI is what?!\"}, {\"output\": \"Amazing!\"})\n", - "memory.save_context({\"input\": \"Backpropagation is what?\"}, {\"output\": \"Beautiful!\"})\n", - "memory.save_context({\"input\": \"Chatbots are what?\"}, {\"output\": \"Charming!\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "id": "284288e1", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'AI: Beautiful!\\nHuman: Chatbots are what?\\nAI: Charming!'}" - ] - }, - "execution_count": 79, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "7b62b2e1", - "metadata": {}, - "source": [ - "可以看到前面超出的的token已经被舍弃了!!!" - ] - }, - { - "cell_type": "markdown", - "id": "f7f6be43", - "metadata": {}, - "source": [ - "### 4.2 中文版" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "id": "e9191020", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': 'AI: 轻舟已过万重山。'}" - ] - }, - "execution_count": 80, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", - "memory.save_context({\"input\": \"朝辞白帝彩云间,\"}, {\"output\": \"千里江陵一日还。\"})\n", - "memory.save_context({\"input\": \"两岸猿声啼不住,\"}, {\"output\": \"轻舟已过万重山。\"})\n", - "memory.load_memory_variables({})" - ] - }, - { - "cell_type": "markdown", - "id": "fb08ef4a-876f-422a-81f9-4805288e5955", - "metadata": {}, - "source": [ - "### 4.3 补充" - ] - }, - { - "cell_type": "markdown", - "id": "5e4d918b", - "metadata": {}, - "source": [ - "ChatGPT使用一种基于字节对编码(Byte Pair Encoding,BPE)的方法来进行tokenization(将输入文本拆分为token)。BPE是一种常见的tokenization技术,它将输入文本分割成较小的子词单元。 \n", - "\n", - "OpenAI在其官方GitHub上公开了一个最新的开源Python库 [tiktoken](https://github.com/openai/tiktoken),这个库主要是用来计算tokens数量的。相比较HuggingFace的tokenizer,其速度提升了好几倍。\n", - "\n", - "具体token计算方式,特别是汉字和英文单词的token区别,具体课参考[知乎文章](https://www.zhihu.com/question/594159910) 。" - ] - }, - { - "cell_type": "markdown", - "id": "5ff55d5d", - "metadata": {}, - "source": [ - "## 五、对话摘要缓存储存" - ] - }, - { - "cell_type": "markdown", - "id": "7d39b83a", - "metadata": {}, - "source": [ - "对话摘要缓存储存,**使用LLM编写到目前为止历史对话的摘要**,并将其保存" - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "id": "72dcf8b1", - "metadata": { - "height": 64 - }, - "outputs": [], - "source": [ - "from langchain.chains import ConversationChain\n", - "from langchain.chat_models import ChatOpenAI\n", - "from langchain.memory import ConversationSummaryBufferMemory" - ] - }, - { - "cell_type": "markdown", - "id": "243b213e-ce17-46a0-8652-03658ca58dd8", - "metadata": {}, - "source": [ - "### 5.1 英文版" - ] - }, - { - "cell_type": "markdown", - "id": "6572ef39", - "metadata": {}, - "source": [ - "#### 5.1.1 使用对话摘要缓存储存\n", - "\n", - "创建一个长字符串,其中包含某人的日程安排" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "id": "4a5b238f", - "metadata": { - "height": 285 - }, - "outputs": [], - "source": [ - "# 创建一个长字符串\n", - "schedule = \"There is a meeting at 8am with your product team. \\\n", - "You will need your powerpoint presentation prepared. \\\n", - "9am-12pm have time to work on your LangChain \\\n", - "project which will go quickly because Langchain is such a powerful tool. \\\n", - "At Noon, lunch at the italian resturant with a customer who is driving \\\n", - "from over an hour away to meet you to understand the latest in AI. \\\n", - "Be sure to bring your laptop to show the latest LLM demo.\"\n", - "\n", - "# 使用对话摘要缓存记忆\n", - "llm = ChatOpenAI(temperature=0.0)\n", - "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100) \n", - "memory.save_context({\"input\": \"Hello\"}, {\"output\": \"What's up\"})\n", - "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})\n", - "memory.save_context(\n", - " {\"input\": \"What is on the schedule today?\"}, {\"output\": f\"{schedule}\"}\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "id": "15226a41-ab36-43a0-93f7-c03c6b374936", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({})['history'])" - ] - }, - { - "cell_type": "markdown", - "id": "7ccb97b6", - "metadata": {}, - "source": [ - "#### 5.1.2 基于对话摘要缓存储存的对话链\n", - "基于上面的对话摘要缓存储存,新建一个对话链" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "id": "6728edba", - "metadata": { - "height": 99 - }, - "outputs": [], - "source": [ - "conversation = ConversationChain(llm=llm, memory=memory, verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "id": "9a221b1d", - "metadata": { - "height": 47 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n", - "Human: What would be a good demo to show?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.'" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"What would be a good demo to show?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "id": "bb582617", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting. A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({})['history'])" - ] - }, - { - "cell_type": "markdown", - "id": "4ba827aa", - "metadata": { - "height": 31 - }, - "source": [ - "### 5.2 中文版" - ] - }, - { - "cell_type": "markdown", - "id": "64898f33-c538-4e68-b008-7123870b692b", - "metadata": {}, - "source": [ - "#### 5.2.1 使用对话摘要缓存储存\n", - "\n", - "创建一个长字符串,其中包含某人的日程安排" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "id": "2c07922b", - "metadata": { - "height": 31 - }, - "outputs": [], - "source": [ - "# 创建一个长字符串\n", - "schedule = \"在八点你和你的产品团队有一个会议。 \\\n", - "你需要做一个PPT。 \\\n", - "上午9点到12点你需要忙于LangChain。\\\n", - "Langchain是一个有用的工具,因此你的项目进展的非常快。\\\n", - "中午,在意大利餐厅与一位开车来的顾客共进午餐 \\\n", - "走了一个多小时的路程与你见面,只为了解最新的 AI。 \\\n", - "确保你带了笔记本电脑可以展示最新的 LLM 样例.\"\n", - "\n", - "llm = ChatOpenAI(temperature=0.0)\n", - "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)\n", - "memory.save_context({\"input\": \"你好,我叫皮皮鲁\"}, {\"output\": \"你好啊,我叫鲁西西\"})\n", - "memory.save_context({\"input\": \"很高兴和你成为朋友!\"}, {\"output\": \"是的,让我们一起去冒险吧!\"})\n", - "memory.save_context({\"input\": \"今天的日程安排是什么?\"}, {\"output\": f\"{schedule}\"})" - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "id": "17424a12-430f-4529-9067-300978c6169e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n" - ] - } - ], - "source": [ - "print(memory.load_memory_variables({})['history'])" - ] - }, - { - "cell_type": "markdown", - "id": "9e29a956-607a-4247-9eb5-01285a370991", - "metadata": {}, - "source": [ - "#### 5.1.2 基于对话摘要缓存储存的对话链\n", - "基于上面的对话摘要缓存储存,新建一个对话链" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "id": "52696c8c", - "metadata": { - "height": 31 - }, - "outputs": [], - "source": [ - "conversation = ConversationChain(llm=llm, memory=memory, verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "id": "48690d13", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "Prompt after formatting:\n", - "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", - "\n", - "Current conversation:\n", - "System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n", - "Human: 展示什么样的样例最好呢?\n", - "AI:\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'展示一些具有多样性和创新性的样例可能是最好的选择。你可以选择展示一些基于图像识别的样例,比如人脸识别、物体识别等。另外,你也可以展示一些自然语言处理方面的样例,比如文本生成、情感分析等。最重要的是选择那些能够展示出你们团队的技术实力和创造力的样例。'" - ] - }, - "execution_count": 100, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "conversation.predict(input=\"展示什么样的样例最好呢?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "id": "85bba1f8", - "metadata": { - "height": 31 - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'history': \"System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples. The human asks what kind of samples would be best to showcase. The AI suggests that showcasing diverse and innovative samples would be the best choice. They recommend selecting samples based on image recognition, such as face recognition and object recognition. Additionally, they suggest showcasing samples related to natural language processing, such as text generation and sentiment analysis. The AI emphasizes the importance of choosing samples that demonstrate the team's technical expertise and creativity.\"}" - ] - }, - "execution_count": 101, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "memory.load_memory_variables({}) # 摘要记录更新了" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.12" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": false, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{"cells": [{"cell_type": "markdown", "id": "a786c77c", "metadata": {"tags": []}, "source": ["# \u7b2c\u4e09\u7ae0 \u50a8\u5b58\n", "\n", " - [\u4e00\u3001\u8bbe\u7f6eOpenAI API Key](#\u4e00\u3001\u8bbe\u7f6eOpenAI-API-Key)\n", " - [\u4e8c\u3001\u5bf9\u8bdd\u7f13\u5b58\u50a8\u5b58](#\u4e8c\u3001\u5bf9\u8bdd\u7f13\u5b58\u50a8\u5b58)\n", " - [2.1 \u82f1\u6587\u7248](#2.1-\u82f1\u6587\u7248)\n", " - [2.1.1 \u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b](#2.1.1-\u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b)\n", " - [2.1.2 \u7b2c\u4e00\u8f6e\u5bf9\u8bdd](#2.1.2-\u7b2c\u4e00\u8f6e\u5bf9\u8bdd)\n", " - [2.1.3 \u7b2c\u4e8c\u8f6e\u5bf9\u8bdd](#2.1.3-\u7b2c\u4e8c\u8f6e\u5bf9\u8bdd)\n", " - [2.1.4 \u7b2c\u4e09\u8f6e\u5bf9\u8bdd](#2.1.4-\u7b2c\u4e09\u8f6e\u5bf9\u8bdd)\n", " - [2.1.5 \u67e5\u770b\u50a8\u5b58\u7f13\u5b58](#2.1.5-\u67e5\u770b\u50a8\u5b58\u7f13\u5b58)\n", " - [2.1.6 \u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58](#2.1.6-\u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58)\n", " - [2.2 \u4e2d\u6587\u7248](#2.2-\u4e2d\u6587\u7248)\n", " - [2.1.1 \u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b](#2.1.1-\u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b)\n", " - [2.1.2 \u7b2c\u4e00\u8f6e\u5bf9\u8bdd](#2.1.2-\u7b2c\u4e00\u8f6e\u5bf9\u8bdd)\n", " - [2.1.3 \u7b2c\u4e8c\u8f6e\u5bf9\u8bdd](#2.1.3-\u7b2c\u4e8c\u8f6e\u5bf9\u8bdd)\n", " - [2.1.4 \u7b2c\u4e09\u8f6e\u5bf9\u8bdd](#2.1.4-\u7b2c\u4e09\u8f6e\u5bf9\u8bdd)\n", " - [2.1.5 \u67e5\u770b\u50a8\u5b58\u7f13\u5b58](#2.1.5-\u67e5\u770b\u50a8\u5b58\u7f13\u5b58)\n", " - [2.1.6 \u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58](#2.1.6-\u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58)\n", " - [2.3 \u603b\u7ed3](#2.3-\u603b\u7ed3)\n", " - [\u4e09\u3001\u5bf9\u8bdd\u7f13\u5b58\u7a97\u53e3\u50a8\u5b58](#\u4e09\u3001\u5bf9\u8bdd\u7f13\u5b58\u7a97\u53e3\u50a8\u5b58)\n", " - [3.1 \u82f1\u6587\u7248](#3.1-\u82f1\u6587\u7248)\n", " - [3.1.1 \u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58](#3.1.1-\u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58)\n", " - [3.1.2 \u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58](#3.1.2-\u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58)\n", " - [3.2 \u4e2d\u6587\u7248](#3.2-\u4e2d\u6587\u7248)\n", " - [3.1.1 \u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58](#3.1.1-\u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58)\n", " - [3.1.2 \u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58](#3.1.2-\u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58)\n", " - [\u56db\u3001\u5bf9\u8bddtoken\u7f13\u5b58\u50a8\u5b58](#\u56db\u3001\u5bf9\u8bddtoken\u7f13\u5b58\u50a8\u5b58)\n", " - [4.1 \u82f1\u6587\u7248](#4.1-\u82f1\u6587\u7248)\n", " - [4.2 \u4e2d\u6587\u7248](#4.2-\u4e2d\u6587\u7248)\n", " - [4.3 \u8865\u5145](#4.3-\u8865\u5145)\n", " - [\u4e94\u3001\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58](#\u4e94\u3001\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58)\n", " - [5.1 \u82f1\u6587\u7248](#5.1-\u82f1\u6587\u7248)\n", " - [5.1.1 \u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58](#5.1.1-\u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58)\n", " - [5.1.2 \u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe](#5.1.2-\u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe)\n", " - [5.2 \u4e2d\u6587\u7248](#5.2-\u4e2d\u6587\u7248)\n", " - [5.2.1 \u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58](#5.2.1-\u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58)\n", " - [5.1.2 \u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe](#5.1.2-\u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe)\n"]}, {"cell_type": "markdown", "id": "7e10db6f", "metadata": {}, "source": ["\u5f53\u4f60\u4e0e\u90a3\u4e9b\u8bed\u8a00\u6a21\u578b\u8fdb\u884c\u4ea4\u4e92\u7684\u65f6\u5019\uff0c\u4ed6\u4eec\u4e0d\u4f1a\u8bb0\u5f97\u4f60\u4e4b\u524d\u548c\u4ed6\u8fdb\u884c\u7684\u4ea4\u6d41\u5185\u5bb9\uff0c\u8fd9\u5728\u6211\u4eec\u6784\u5efa\u4e00\u4e9b\u5e94\u7528\u7a0b\u5e8f\uff08\u5982\u804a\u5929\u673a\u5668\u4eba\uff09\u7684\u65f6\u5019\uff0c\u662f\u4e00\u4e2a\u5f88\u5927\u7684\u95ee\u9898 -- \u663e\u5f97\u4e0d\u591f\u667a\u80fd\uff01\u56e0\u6b64\uff0c\u5728\u672c\u8282\u4e2d\u6211\u4eec\u5c06\u4ecb\u7ecd LangChain \u4e2d\u7684\u50a8\u5b58\u6a21\u5757\uff0c\u5373\u5982\u4f55\u5c06\u5148\u524d\u7684\u5bf9\u8bdd\u5d4c\u5165\u5230\u8bed\u8a00\u6a21\u578b\u4e2d\u7684\uff0c\u4f7f\u5176\u5177\u6709\u8fde\u7eed\u5bf9\u8bdd\u7684\u80fd\u529b\u3002\n", "\n", "\u5f53\u4f7f\u7528 LangChain \u4e2d\u7684\u50a8\u5b58(Memory)\u6a21\u5757\u65f6\uff0c\u5b83\u53ef\u4ee5\u5e2e\u52a9\u4fdd\u5b58\u548c\u7ba1\u7406\u5386\u53f2\u804a\u5929\u6d88\u606f\uff0c\u4ee5\u53ca\u6784\u5efa\u5173\u4e8e\u7279\u5b9a\u5b9e\u4f53\u7684\u77e5\u8bc6\u3002\u8fd9\u4e9b\u7ec4\u4ef6\u53ef\u4ee5\u8de8\u591a\u8f6e\u5bf9\u8bdd\u50a8\u5b58\u4fe1\u606f\uff0c\u5e76\u5141\u8bb8\u5728\u5bf9\u8bdd\u671f\u95f4\u8ddf\u8e2a\u7279\u5b9a\u4fe1\u606f\u548c\u4e0a\u4e0b\u6587\u3002\n", "\n", "LangChain \u63d0\u4f9b\u4e86\u591a\u79cd\u50a8\u5b58\u7c7b\u578b\u3002\u5176\u4e2d\uff0c\u7f13\u51b2\u533a\u50a8\u5b58\u5141\u8bb8\u4fdd\u7559\u6700\u8fd1\u7684\u804a\u5929\u6d88\u606f\uff0c\u6458\u8981\u50a8\u5b58\u5219\u63d0\u4f9b\u4e86\u5bf9\u6574\u4e2a\u5bf9\u8bdd\u7684\u6458\u8981\u3002\u5b9e\u4f53\u50a8\u5b58 \u5219\u5141\u8bb8\u5728\u591a\u8f6e\u5bf9\u8bdd\u4e2d\u4fdd\u7559\u6709\u5173\u7279\u5b9a\u5b9e\u4f53\u7684\u4fe1\u606f\u3002\u8fd9\u4e9b\u8bb0\u5fc6\u7ec4\u4ef6\u90fd\u662f\u6a21\u5757\u5316\u7684\uff0c\u53ef\u4e0e\u5176\u4ed6\u7ec4\u4ef6\u7ec4\u5408\u4f7f\u7528\uff0c\u4ece\u800c\u589e\u5f3a\u673a\u5668\u4eba\u7684\u5bf9\u8bdd\u7ba1\u7406\u80fd\u529b\u3002\u50a8\u5b58\u6a21\u5757\u53ef\u4ee5\u901a\u8fc7\u7b80\u5355\u7684API\u8c03\u7528\u6765\u8bbf\u95ee\u548c\u66f4\u65b0\uff0c\u5141\u8bb8\u5f00\u53d1\u4eba\u5458\u66f4\u8f7b\u677e\u5730\u5b9e\u73b0\u5bf9\u8bdd\u5386\u53f2\u8bb0\u5f55\u7684\u7ba1\u7406\u548c\u7ef4\u62a4\u3002\n", "\n", "\u6b64\u6b21\u8bfe\u7a0b\u4e3b\u8981\u4ecb\u7ecd\u5176\u4e2d\u56db\u79cd\u50a8\u5b58\u6a21\u5757\uff0c\u5176\u4ed6\u6a21\u5757\u53ef\u67e5\u770b\u6587\u6863\u5b66\u4e60\u3002\n", "- \u5bf9\u8bdd\u7f13\u5b58\u50a8\u5b58 (ConversationBufferMemory\uff09\n", "- \u5bf9\u8bdd\u7f13\u5b58\u7a97\u53e3\u50a8\u5b58 (ConversationBufferWindowMemory\uff09\n", "- \u5bf9\u8bdd\u4ee4\u724c\u7f13\u5b58\u50a8\u5b58 (ConversationTokenBufferMemory\uff09\n", "- \u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58 (ConversationSummaryBufferMemory\uff09\n", "\n", "\u5728LangChain\u4e2d\uff0c\u50a8\u5b58 \u6307\u7684\u662f\u5927\u8bed\u8a00\u6a21\u578b\uff08LLM\uff09\u7684\u77ed\u671f\u8bb0\u5fc6\u3002\u4e3a\u4ec0\u4e48\u662f\u77ed\u671f\u8bb0\u5fc6\uff1f\u90a3\u662f\u56e0\u4e3aLLM\u8bad\u7ec3\u597d\u4e4b\u540e (\u83b7\u5f97\u4e86\u4e00\u4e9b\u957f\u671f\u8bb0\u5fc6)\uff0c\u5b83\u7684\u53c2\u6570\u4fbf\u4e0d\u4f1a\u56e0\u4e3a\u7528\u6237\u7684\u8f93\u5165\u800c\u53d1\u751f\u6539\u53d8\u3002\u5f53\u7528\u6237\u4e0e\u8bad\u7ec3\u597d\u7684LLM\u8fdb\u884c\u5bf9\u8bdd\u65f6\uff0cLLM\u4f1a\u6682\u65f6\u8bb0\u4f4f\u7528\u6237\u7684\u8f93\u5165\u548c\u5b83\u5df2\u7ecf\u751f\u6210\u7684\u8f93\u51fa\uff0c\u4ee5\u4fbf\u9884\u6d4b\u4e4b\u540e\u7684\u8f93\u51fa\uff0c\u800c\u6a21\u578b\u8f93\u51fa\u5b8c\u6bd5\u540e\uff0c\u5b83\u4fbf\u4f1a\u201c\u9057\u5fd8\u201d\u4e4b\u524d\u7528\u6237\u7684\u8f93\u5165\u548c\u5b83\u7684\u8f93\u51fa\u3002\u56e0\u6b64\uff0c\u4e4b\u524d\u7684\u8fd9\u4e9b\u4fe1\u606f\u53ea\u80fd\u79f0\u4f5c\u4e3aLLM\u7684\u77ed\u671f\u8bb0\u5fc6\u3002 \n", " \n", "\u4e3a\u4e86\u5ef6\u957fLLM\u77ed\u671f\u8bb0\u5fc6\u7684\u4fdd\u7559\u65f6\u95f4\uff0c\u5219\u9700\u8981\u501f\u52a9\u4e00\u4e9b\u5916\u90e8\u50a8\u5b58\u65b9\u5f0f\u6765\u8fdb\u884c\u8bb0\u5fc6\uff0c\u4ee5\u4fbf\u5728\u7528\u6237\u4e0eLLM\u5bf9\u8bdd\u4e2d\uff0cLLM\u80fd\u591f\u5c3d\u53ef\u80fd\u7684\u77e5\u9053\u7528\u6237\u4e0e\u5b83\u6240\u8fdb\u884c\u7684\u5386\u53f2\u5bf9\u8bdd\u4fe1\u606f\u3002 "]}, {"cell_type": "markdown", "id": "1ca56e6b-1e07-4405-a1ca-f4237f20fa75", "metadata": {"jp-MarkdownHeadingCollapsed": true, "tags": []}, "source": ["## \u4e00\u3001\u8bbe\u7f6eOpenAI API Key\n", "\n", "\u767b\u9646 [OpenAI \u8d26\u6237](https://platform.openai.com/account/api-keys) \u83b7\u53d6API Key\uff0c\u7136\u540e\u5c06\u5176\u8bbe\u7f6e\u4e3a\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u5168\u5c40\u73af\u5883\u53d8\u91cf\uff0c\u53ef\u4ee5\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://zhuanlan.zhihu.com/p/627665725)\u3002\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u672c\u5730/\u9879\u76ee\u73af\u5883\u53d8\u91cf\uff0c\u5728\u672c\u6587\u4ef6\u76ee\u5f55\u4e0b\u521b\u5efa`.env`\u6587\u4ef6, \u6253\u5f00\u6587\u4ef6\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u3002\n", "\n", "

\n", " OPENAI_API_KEY=\"your_api_key\" \n", "

\n", " \n", " \u66ff\u6362\"your_api_key\"\u4e3a\u4f60\u81ea\u5df1\u7684 API Key"]}, {"cell_type": "code", "execution_count": null, "id": "6932bd47-c6d5-4794-8102-a12b84412a93", "metadata": {}, "outputs": [], "source": ["# \u4e0b\u8f7d\u9700\u8981\u7684\u5305python-dotenv\u548copenai\n", "# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q\n", "!pip install -q python-dotenv\n", "!pip install -q openai"]}, {"cell_type": "code", "execution_count": 1, "id": "10446712-9fa6-4d71-94ce-2ea4cf197e54", "metadata": {}, "outputs": [], "source": ["import os\n", "\n", "import openai\n", "from dotenv import find_dotenv, load_dotenv\n", "\n", "# \u8bfb\u53d6\u672c\u5730/\u9879\u76ee\u7684\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "# find_dotenv()\u5bfb\u627e\u5e76\u5b9a\u4f4d.env\u6587\u4ef6\u7684\u8def\u5f84\n", "# load_dotenv()\u8bfb\u53d6\u8be5.env\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u52a0\u8f7d\u5230\u5f53\u524d\u7684\u8fd0\u884c\u73af\u5883\u4e2d\n", "# \u5982\u679c\u4f60\u8bbe\u7f6e\u7684\u662f\u5168\u5c40\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u884c\u4ee3\u7801\u5219\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n", "_ = load_dotenv(find_dotenv())\n", "\n", "# \u83b7\u53d6\u73af\u5883\u53d8\u91cf OPENAI_API_KEY\n", "openai.api_key = os.environ[\"OPENAI_API_KEY\"]"]}, {"cell_type": "markdown", "id": "1297dcd5", "metadata": {"tags": []}, "source": ["## \u4e8c\u3001\u5bf9\u8bdd\u7f13\u5b58\u50a8\u5b58\n", " "]}, {"cell_type": "markdown", "id": "ffa8cd26-45c5-4bae-90b2-b07d23bf3bb2", "metadata": {}, "source": ["### 2.1 \u82f1\u6587\u7248"]}, {"cell_type": "markdown", "id": "b7e77a3d-7aaa-48c1-b219-19bd6f4eb674", "metadata": {"tags": []}, "source": ["#### 2.1.1 \u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 47, "id": "20ad6fe2", "metadata": {"height": 98}, "outputs": [], "source": ["from langchain.chains import ConversationChain\n", "from langchain.chat_models import ChatOpenAI\n", "from langchain.memory import ConversationBufferMemory"]}, {"cell_type": "code", "execution_count": 48, "id": "88bdf13d", "metadata": {"height": 133}, "outputs": [], "source": ["# \u8fd9\u91cc\u6211\u4eec\u5c06\u53c2\u6570temperature\u8bbe\u7f6e\u4e3a0.0\uff0c\u4ece\u800c\u51cf\u5c11\u751f\u6210\u7b54\u6848\u7684\u968f\u673a\u6027\u3002\n", "# \u5982\u679c\u4f60\u60f3\u8981\u6bcf\u6b21\u5f97\u5230\u4e0d\u4e00\u6837\u7684\u6709\u65b0\u610f\u7684\u7b54\u6848\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u589e\u5927\u8be5\u53c2\u6570\u3002\n", "llm = ChatOpenAI(temperature=0.0) \n", "\n", "memory = ConversationBufferMemory()\n", "\n", "# \u65b0\u5efa\u4e00\u4e2a ConversationChain Class \u5b9e\u4f8b\n", "# verbose\u53c2\u6570\u8bbe\u7f6e\u4e3aTrue\u65f6\uff0c\u7a0b\u5e8f\u4f1a\u8f93\u51fa\u66f4\u8be6\u7ec6\u7684\u4fe1\u606f\uff0c\u4ee5\u63d0\u4f9b\u66f4\u591a\u7684\u8c03\u8bd5\u6216\u8fd0\u884c\u65f6\u4fe1\u606f\u3002\n", "# \u76f8\u53cd\uff0c\u5f53\u5c06verbose\u53c2\u6570\u8bbe\u7f6e\u4e3aFalse\u65f6\uff0c\u7a0b\u5e8f\u4f1a\u4ee5\u66f4\u7b80\u6d01\u7684\u65b9\u5f0f\u8fd0\u884c\uff0c\u53ea\u8f93\u51fa\u5173\u952e\u7684\u4fe1\u606f\u3002\n", "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )"]}, {"cell_type": "markdown", "id": "dea83837", "metadata": {"tags": []}, "source": ["#### 2.1.2 \u7b2c\u4e00\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "markdown", "id": "1a3b4c42", "metadata": {}, "source": ["\u5f53\u6211\u4eec\u8fd0\u884c\u9884\u6d4b(predict)\u65f6\uff0c\u751f\u6210\u4e86\u4e00\u4e9b\u63d0\u793a\uff0c\u5982\u4e0b\u6240\u89c1\uff0c\u4ed6\u8bf4\u201c\u4ee5\u4e0b\u662f\u4eba\u7c7b\u548cAI\u4e4b\u95f4\u53cb\u597d\u7684\u5bf9\u8bdd\uff0cAI\u5065\u8c08\u201c\u7b49\u7b49\uff0c\u8fd9\u5b9e\u9645\u4e0a\u662fLangChain\u751f\u6210\u7684\u63d0\u793a\uff0c\u4ee5\u4f7f\u7cfb\u7edf\u8fdb\u884c\u5e0c\u671b\u548c\u53cb\u597d\u7684\u5bf9\u8bdd\uff0c\u5e76\u4e14\u5fc5\u987b\u4fdd\u5b58\u5bf9\u8bdd\uff0c\u5e76\u63d0\u793a\u4e86\u5f53\u524d\u5df2\u5b8c\u6210\u7684\u6a21\u578b\u94fe\u3002"]}, {"cell_type": "code", "execution_count": 49, "id": "db24677d", "metadata": {"height": 47}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "\n", "Human: Hi, my name is Andrew\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["\"Hello Andrew! It's nice to meet you. How can I assist you today?\""]}, "execution_count": 49, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"Hi, my name is Andrew\")"]}, {"cell_type": "markdown", "id": "e71564ad", "metadata": {}, "source": ["#### 2.1.3 \u7b2c\u4e8c\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "markdown", "id": "54d006bd", "metadata": {}, "source": ["\u5f53\u6211\u4eec\u8fdb\u884c\u7b2c\u4e8c\u8f6e\u5bf9\u8bdd\u65f6\uff0c\u5b83\u4f1a\u4fdd\u7559\u4e0a\u9762\u7684\u63d0\u793a"]}, {"cell_type": "code", "execution_count": 50, "id": "cc3ef937", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "Human: Hi, my name is Andrew\n", "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", "Human: What is 1+1?\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'1+1 is equal to 2.'"]}, "execution_count": 50, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"What is 1+1?\")"]}, {"cell_type": "markdown", "id": "33cb734b", "metadata": {}, "source": ["#### 2.1.4 \u7b2c\u4e09\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "markdown", "id": "0393df3d", "metadata": {}, "source": ["\u4e3a\u4e86\u9a8c\u8bc1\u4ed6\u662f\u5426\u8bb0\u5fc6\u4e86\u524d\u9762\u7684\u5bf9\u8bdd\u5185\u5bb9\uff0c\u6211\u4eec\u8ba9\u4ed6\u56de\u7b54\u524d\u9762\u5df2\u7ecf\u8bf4\u8fc7\u7684\u5185\u5bb9\uff08\u6211\u7684\u540d\u5b57\uff09\uff0c\u53ef\u4ee5\u770b\u5230\u4ed6\u786e\u5b9e\u8f93\u51fa\u4e86\u6b63\u786e\u7684\u540d\u5b57\uff0c\u56e0\u6b64\u8fd9\u4e2a\u5bf9\u8bdd\u94fe\u968f\u7740\u5f80\u4e0b\u8fdb\u884c\u4f1a\u8d8a\u6765\u8d8a\u957f"]}, {"cell_type": "code", "execution_count": 51, "id": "acf3339a", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "Human: Hi, my name is Andrew\n", "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", "Human: What is 1+1?\n", "AI: 1+1 is equal to 2.\n", "Human: What is my name?\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Your name is Andrew.'"]}, "execution_count": 51, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"What is my name?\")"]}, {"cell_type": "markdown", "id": "5a96a8d9", "metadata": {}, "source": ["#### 2.1.5 \u67e5\u770b\u50a8\u5b58\u7f13\u5b58\n", "\n", "\u50a8\u5b58\u7f13\u5b58(memory.buffer)\n", "\u50a8\u5b58\u4e86\u5f53\u524d\u4e3a\u6b62\u6240\u6709\u7684\u5bf9\u8bdd\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 52, "id": "2529400d", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Human: Hi, my name is Andrew\n", "AI: Hello Andrew! It's nice to meet you. How can I assist you today?\n", "Human: What is 1+1?\n", "AI: 1+1 is equal to 2.\n", "Human: What is my name?\n", "AI: Your name is Andrew.\n"]}], "source": ["print(memory.buffer) "]}, {"cell_type": "markdown", "id": "0b5de846", "metadata": {}, "source": ["\u4e5f\u53ef\u4ee5\u901a\u8fc7memory.load_memory_variables({})\u6253\u5370\u7f13\u5b58\u4e2d\u7684\u5386\u53f2\u6d88\u606f\u3002\u8fd9\u91cc\u7684`{}`\u662f\u4e00\u4e2a\u7a7a\u5b57\u5178\uff0c\u6709\u4e00\u4e9b\u66f4\u9ad8\u7ea7\u7684\u529f\u80fd\uff0c\u4f7f\u7528\u6237\u53ef\u4ee5\u4f7f\u7528\u66f4\u590d\u6742\u7684\u8f93\u5165\uff0c\u4f46\u6211\u4eec\u4e0d\u4f1a\u5728\u8fd9\u4e2a\u77ed\u671f\u8bfe\u7a0b\u4e2d\u8ba8\u8bba\u5b83\u4eec\uff0c\u6240\u4ee5\u4e0d\u8981\u62c5\u5fc3\u4e3a\u4ec0\u4e48\u8fd9\u91cc\u6709\u4e00\u4e2a\u7a7a\u7684\u82b1\u62ec\u53f7\u3002"]}, {"cell_type": "code", "execution_count": 53, "id": "5018cb0a", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{'history': \"Human: Hi, my name is Andrew\\nAI: Hello Andrew! It's nice to meet you. How can I assist you today?\\nHuman: What is 1+1?\\nAI: 1+1 is equal to 2.\\nHuman: What is my name?\\nAI: Your name is Andrew.\"}\n"]}], "source": ["print(memory.load_memory_variables({}))"]}, {"cell_type": "markdown", "id": "07d2e892", "metadata": {}, "source": ["#### 2.1.6 \u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58"]}, {"cell_type": "code", "execution_count": 54, "id": "14219b70", "metadata": {"height": 31}, "outputs": [], "source": ["memory = ConversationBufferMemory() # \u65b0\u5efa\u4e00\u4e2a\u7a7a\u7684\u5bf9\u8bdd\u7f13\u5b58\u8bb0\u5fc6"]}, {"cell_type": "code", "execution_count": 55, "id": "a36e9905", "metadata": {"height": 48}, "outputs": [], "source": ["memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"}) # \u5411\u7f13\u5b58\u533a\u6dfb\u52a0\u6307\u5b9a\u5bf9\u8bdd\u7684\u8f93\u5165\u8f93\u51fa"]}, {"cell_type": "code", "execution_count": 56, "id": "61631b1f", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Human: Hi\n", "AI: What's up\n"]}], "source": ["print(memory.buffer) # \u67e5\u770b\u7f13\u5b58\u533a\u7ed3\u679c"]}, {"cell_type": "code", "execution_count": 57, "id": "a2fdf9ec", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{'history': \"Human: Hi\\nAI: What's up\"}\n"]}], "source": ["print(memory.load_memory_variables({}))# \u518d\u6b21\u52a0\u8f7d\u8bb0\u5fc6\u53d8\u91cf"]}, {"cell_type": "markdown", "id": "2ac544f2", "metadata": {}, "source": ["\u7ee7\u7eed\u6dfb\u52a0\u65b0\u7684\u5185\u5bb9\uff0c\u5bf9\u8bdd\u5386\u53f2\u90fd\u4fdd\u5b58\u4e0b\u6765\u5728\u4e86\uff01"]}, {"cell_type": "code", "execution_count": 58, "id": "7ca79256", "metadata": {"height": 64}, "outputs": [], "source": ["memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})"]}, {"cell_type": "code", "execution_count": 59, "id": "890a4497", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["{'history': \"Human: Hi\\nAI: What's up\\nHuman: Not much, just hanging\\nAI: Cool\"}"]}, "execution_count": 59, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "6eddd91a-bf1c-4b82-b99c-c585420e4ecb", "metadata": {}, "source": ["### 2.2 \u4e2d\u6587\u7248"]}, {"cell_type": "markdown", "id": "55b3e4e9-7a6a-4a09-9ac3-0096a67849c7", "metadata": {}, "source": ["#### 2.1.1 \u521d\u59cb\u5316\u5bf9\u8bdd\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 30, "id": "3577aaff-7edb-40b0-866a-e407e63d55e0", "metadata": {"height": 98}, "outputs": [], "source": ["from langchain.chains import ConversationChain\n", "from langchain.chat_models import ChatOpenAI\n", "from langchain.memory import ConversationBufferMemory"]}, {"cell_type": "code", "execution_count": 33, "id": "a77d37ab-1f75-4ae8-8d7c-5066773ead81", "metadata": {"height": 133}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "\n", "Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f'"]}, "execution_count": 33, "metadata": {}, "output_type": "execute_result"}], "source": ["llm = ChatOpenAI(temperature=0.0) \n", "\n", "memory = ConversationBufferMemory()\n", "\n", "conversation = ConversationChain(llm=llm, memory = memory, verbose=True )"]}, {"cell_type": "markdown", "id": "747cb539-abc4-4e47-8cb9-1ee608ab07fc", "metadata": {}, "source": ["#### 2.1.2 \u7b2c\u4e00\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "code", "execution_count": null, "id": "99e48462-7a92-4842-bdaa-2a478ba2252c", "metadata": {}, "outputs": [], "source": ["conversation.predict(input=\"\u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\")"]}, {"cell_type": "markdown", "id": "979d320b-6b20-4722-99db-c48a43711d6c", "metadata": {}, "source": ["#### 2.1.3 \u7b2c\u4e8c\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "code", "execution_count": 34, "id": "6ed6e97a-d7ea-4188-a6d7-f91d2a29d14a", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\n", "AI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\n", "Human: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'1+1\u7b49\u4e8e2\u3002'"]}, "execution_count": 34, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"1+1\u7b49\u4e8e\u591a\u5c11\uff1f\")"]}, {"cell_type": "markdown", "id": "8a1fd531-216e-42d8-b226-839747ad7dd3", "metadata": {}, "source": ["#### 2.1.4 \u7b2c\u4e09\u8f6e\u5bf9\u8bdd"]}, {"cell_type": "code", "execution_count": null, "id": "b5dfe488-2758-42c7-9c20-e483b4c22ab8", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\n", "AI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\n", "Human: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\n", "AI: 1+1\u7b49\u4e8e2\u3002\n", "Human: What is my name?\n", "AI: \u4f60\u7684\u540d\u5b57\u662f\u76ae\u76ae\u9c81\u3002\n", "Human: \u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u4f60\u53eb\u76ae\u76ae\u9c81\u3002'"]}, "execution_count": 36, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"\u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\")"]}, {"cell_type": "markdown", "id": "05d9822e-943d-4905-a1f8-a0d28c215d60", "metadata": {}, "source": ["#### 2.1.5 \u67e5\u770b\u50a8\u5b58\u7f13\u5b58"]}, {"cell_type": "code", "execution_count": 37, "id": "0795580f-b6b6-47e0-8882-26fe204560bd", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\n", "AI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\n", "Human: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\n", "AI: 1+1\u7b49\u4e8e2\u3002\n", "Human: What is my name?\n", "AI: \u4f60\u7684\u540d\u5b57\u662f\u76ae\u76ae\u9c81\u3002\n", "Human: \u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\n", "AI: \u4f60\u53eb\u76ae\u76ae\u9c81\u3002\n"]}], "source": ["print(memory.buffer) "]}, {"cell_type": "code", "execution_count": 38, "id": "dfe7824f-bd6e-4b95-92e2-1c85c62a92e9", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\n", "AI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\n", "Human: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\n", "AI: 1+1\u7b49\u4e8e2\u3002\n", "Human: What is my name?\n", "AI: \u4f60\u7684\u540d\u5b57\u662f\u76ae\u76ae\u9c81\u3002\n", "Human: \u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\n", "AI: \u4f60\u53eb\u76ae\u76ae\u9c81\u3002\n"]}], "source": ["print(memory.buffer) "]}, {"cell_type": "code", "execution_count": 39, "id": "48942759-8afb-4aed-80c5-a48952a2b0c0", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["{'history': 'Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\\nAI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\\nHuman: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\\nAI: 1+1\u7b49\u4e8e2\u3002\\nHuman: What is my name?\\nAI: \u4f60\u7684\u540d\u5b57\u662f\u76ae\u76ae\u9c81\u3002\\nHuman: \u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\\nAI: \u4f60\u53eb\u76ae\u76ae\u9c81\u3002'}\n"]}], "source": ["print(memory.load_memory_variables({}))"]}, {"cell_type": "code", "execution_count": 40, "id": "4d0c4625-e928-45dc-b8da-4ab865ac5f7e", "metadata": {}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: \u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\\nAI: \u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\\nHuman: 1+1\u7b49\u4e8e\u591a\u5c11\uff1f\\nAI: 1+1\u7b49\u4e8e2\u3002\\nHuman: What is my name?\\nAI: \u4f60\u7684\u540d\u5b57\u662f\u76ae\u76ae\u9c81\u3002\\nHuman: \u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\\nAI: \u4f60\u53eb\u76ae\u76ae\u9c81\u3002'}"]}, "execution_count": 40, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "80f3778e-5fbf-43ed-9df1-d57d98ec6fb0", "metadata": {}, "source": ["#### 2.1.6 \u76f4\u63a5\u6dfb\u52a0\u5185\u5bb9\u5230\u50a8\u5b58\u7f13\u5b58"]}, {"cell_type": "code", "execution_count": 42, "id": "147b2c30-1662-4b49-aaf8-c228428e5cc6", "metadata": {}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: \u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\\nAI: \u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f'}"]}, "execution_count": 42, "metadata": {}, "output_type": "execute_result"}], "source": ["memory = ConversationBufferMemory()\n", "memory.save_context({\"input\": \"\u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\"}, {\"output\": \"\u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f\"})\n", "memory.load_memory_variables({})"]}, {"cell_type": "code", "execution_count": 43, "id": "6b5e27f0-dad7-41b6-9326-bebf6299638f", "metadata": {"height": 64}, "outputs": [], "source": ["memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})"]}, {"cell_type": "code", "execution_count": 44, "id": "cfa7c555-06ab-4906-b3dc-906f789e08f5", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: \u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\\nAI: \u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f\\nHuman: Not much, just hanging\\nAI: Cool'}"]}, "execution_count": 44, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.load_memory_variables({})"]}, {"cell_type": "code", "execution_count": 45, "id": "deb33de8-37ea-4180-a73e-0fc456b14eb0", "metadata": {}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: \u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\\nAI: \u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f\\nHuman: Not much, just hanging\\nAI: Cool\\nHuman: \u5f88\u9ad8\u5174\u548c\u4f60\u6210\u4e3a\u670b\u53cb\uff01\\nAI: \u662f\u7684\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u53bb\u5192\u9669\u5427\uff01'}"]}, "execution_count": 45, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.save_context({\"input\": \"\u5f88\u9ad8\u5174\u548c\u4f60\u6210\u4e3a\u670b\u53cb\uff01\"}, {\"output\": \"\u662f\u7684\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u53bb\u5192\u9669\u5427\uff01\"})\n", "memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "10146f1a-0114-4902-8122-d19ae6f7c461", "metadata": {}, "source": ["### 2.3 \u603b\u7ed3"]}, {"cell_type": "markdown", "id": "2759b6bc-edb2-4cfe-b0f8-1bf6c4d796f9", "metadata": {}, "source": ["\u5f53\u6211\u4eec\u5728\u4f7f\u7528\u5927\u578b\u8bed\u8a00\u6a21\u578b\u8fdb\u884c\u804a\u5929\u5bf9\u8bdd\u65f6\uff0c**\u5927\u578b\u8bed\u8a00\u6a21\u578b\u672c\u8eab\u5b9e\u9645\u4e0a\u662f\u65e0\u72b6\u6001\u7684\u3002\u8bed\u8a00\u6a21\u578b\u672c\u8eab\u5e76\u4e0d\u8bb0\u5f97\u5230\u76ee\u524d\u4e3a\u6b62\u7684\u5386\u53f2\u5bf9\u8bdd**\u3002\u6bcf\u6b21\u8c03\u7528API\u7ed3\u70b9\u90fd\u662f\u72ec\u7acb\u7684\u3002\u50a8\u5b58(Memory)\u53ef\u4ee5\u50a8\u5b58\u5230\u76ee\u524d\u4e3a\u6b62\u7684\u6240\u6709\u672f\u8bed\u6216\u5bf9\u8bdd\uff0c\u5e76\u5c06\u5176\u8f93\u5165\u6216\u9644\u52a0\u4e0a\u4e0b\u6587\u5230LLM\u4e2d\u7528\u4e8e\u751f\u6210\u8f93\u51fa\u3002\u5982\u6b64\u770b\u8d77\u6765\u5c31\u597d\u50cf\u5b83\u5728\u8fdb\u884c\u4e0b\u4e00\u8f6e\u5bf9\u8bdd\u7684\u65f6\u5019\uff0c\u8bb0\u5f97\u4e4b\u524d\u8bf4\u8fc7\u4ec0\u4e48\u3002\n"]}, {"cell_type": "markdown", "id": "cf98e9ff", "metadata": {}, "source": ["## \u4e09\u3001\u5bf9\u8bdd\u7f13\u5b58\u7a97\u53e3\u50a8\u5b58\n", " \n", "\u968f\u7740\u5bf9\u8bdd\u53d8\u5f97\u8d8a\u6765\u8d8a\u957f\uff0c\u6240\u9700\u7684\u5185\u5b58\u91cf\u4e5f\u53d8\u5f97\u975e\u5e38\u957f\u3002\u5c06\u5927\u91cf\u7684tokens\u53d1\u9001\u5230LLM\u7684\u6210\u672c\uff0c\u4e5f\u4f1a\u53d8\u5f97\u66f4\u52a0\u6602\u8d35,\u8fd9\u4e5f\u5c31\u662f\u4e3a\u4ec0\u4e48API\u7684\u8c03\u7528\u8d39\u7528\uff0c\u901a\u5e38\u662f\u57fa\u4e8e\u5b83\u9700\u8981\u5904\u7406\u7684tokens\u6570\u91cf\u800c\u6536\u8d39\u7684\u3002\n", " \n", "\u9488\u5bf9\u4ee5\u4e0a\u95ee\u9898\uff0cLangChain\u4e5f\u63d0\u4f9b\u4e86\u51e0\u79cd\u65b9\u4fbf\u7684\u50a8\u5b58\u65b9\u5f0f\u6765\u4fdd\u5b58\u5386\u53f2\u5bf9\u8bdd\u3002\u5176\u4e2d\uff0c\u5bf9\u8bdd\u7f13\u5b58\u7a97\u53e3\u50a8\u5b58\u53ea\u4fdd\u7559\u4e00\u4e2a\u7a97\u53e3\u5927\u5c0f\u7684\u5bf9\u8bdd\u3002\u5b83\u53ea\u4f7f\u7528\u6700\u8fd1\u7684n\u6b21\u4ea4\u4e92\u3002\u8fd9\u53ef\u4ee5\u7528\u4e8e\u4fdd\u6301\u6700\u8fd1\u4ea4\u4e92\u7684\u6ed1\u52a8\u7a97\u53e3\uff0c\u4ee5\u4fbf\u7f13\u51b2\u533a\u4e0d\u4f1a\u8fc7\u5927"]}, {"cell_type": "markdown", "id": "b63c9061-9916-4524-b497-93a0aa2b7d06", "metadata": {}, "source": ["### 3.1 \u82f1\u6587\u7248"]}, {"cell_type": "markdown", "id": "641477a4", "metadata": {}, "source": ["#### 3.1.1 \u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58"]}, {"cell_type": "code", "execution_count": 65, "id": "3ea6233e", "metadata": {"height": 47}, "outputs": [], "source": ["from langchain.memory import ConversationBufferWindowMemory\n", "\n", "# k \u4e3a\u7a97\u53e3\u53c2\u6570\uff0ck=1\u8868\u660e\u53ea\u4fdd\u7559\u4e00\u4e2a\u5bf9\u8bdd\u8bb0\u5fc6\n", "memory = ConversationBufferWindowMemory(k=1) "]}, {"cell_type": "code", "execution_count": 66, "id": "dc4553fb", "metadata": {"height": 115}, "outputs": [], "source": ["# \u5411memory\u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\n", "memory.save_context({\"input\": \"Hi\"}, {\"output\": \"What's up\"})\n", "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})"]}, {"cell_type": "code", "execution_count": 67, "id": "6a788403", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: Not much, just hanging\\nAI: Cool'}"]}, "execution_count": 67, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u5e76\u67e5\u770b\u8bb0\u5fc6\u53d8\u91cf\u5f53\u524d\u7684\u8bb0\u5f55\n", "memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "63bda148", "metadata": {}, "source": ["#### 3.1.2 \u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58"]}, {"cell_type": "code", "execution_count": 68, "id": "4087bc87", "metadata": {"height": 133}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.0)\n", "memory = ConversationBufferWindowMemory(k=1)\n", "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )"]}, {"cell_type": "markdown", "id": "b6d661e3", "metadata": {}, "source": ["\u6ce8\u610f\u6b64\u5904\uff01\u7531\u4e8e\u8fd9\u91cc\u7528\u7684\u662f\u4e00\u4e2a\u7a97\u53e3\u7684\u8bb0\u5fc6\uff0c\u56e0\u6b64\u53ea\u80fd\u4fdd\u5b58\u4e00\u8f6e\u7684\u5386\u53f2\u6d88\u606f\uff0c\u56e0\u6b64AI\u5e76\u4e0d\u80fd\u77e5\u9053\u4f60\u7b2c\u4e00\u8f6e\u5bf9\u8bdd\u4e2d\u63d0\u5230\u7684\u540d\u5b57\uff0c\u4ed6\u6700\u591a\u53ea\u80fd\u8bb0\u4f4f\u4e0a\u4e00\u8f6e\uff08\u7b2c\u4e8c\u8f6e\uff09\u7684\u5bf9\u8bdd\u4fe1\u606f"]}, {"cell_type": "code", "execution_count": 69, "id": "4faaa952", "metadata": {"height": 47}, "outputs": [{"data": {"text/plain": ["\"Hello Andrew! It's nice to meet you. How can I assist you today?\""]}, "execution_count": 69, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"Hi, my name is Andrew\")"]}, {"cell_type": "code", "execution_count": 70, "id": "bb20ddaa", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["'1+1 is equal to 2.'"]}, "execution_count": 70, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"What is 1+1?\")"]}, {"cell_type": "code", "execution_count": 71, "id": "489b2194", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["\"I'm sorry, but I don't have access to personal information.\""]}, "execution_count": 71, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"What is my name?\")"]}, {"cell_type": "markdown", "id": "88837e7c-cf4b-469e-b820-bbfc49ba876c", "metadata": {}, "source": ["### 3.2 \u4e2d\u6587\u7248"]}, {"cell_type": "markdown", "id": "760ec3ad-6959-4a36-b1b5-4fcafe8088ad", "metadata": {}, "source": ["#### 3.1.1 \u6dfb\u52a0\u4e24\u8f6e\u5bf9\u8bdd\u5230\u7a97\u53e3\u50a8\u5b58"]}, {"cell_type": "code", "execution_count": 72, "id": "68a2907c", "metadata": {}, "outputs": [{"data": {"text/plain": ["{'history': 'Human: \u5f88\u9ad8\u5174\u548c\u4f60\u6210\u4e3a\u670b\u53cb\uff01\\nAI: \u662f\u7684\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u53bb\u5192\u9669\u5427\uff01'}"]}, "execution_count": 72, "metadata": {}, "output_type": "execute_result"}], "source": ["from langchain.memory import ConversationBufferWindowMemory\n", "\n", "# k=1\u8868\u660e\u53ea\u4fdd\u7559\u4e00\u4e2a\u5bf9\u8bdd\u8bb0\u5fc6\n", "memory = ConversationBufferWindowMemory(k=1) \n", "memory.save_context({\"input\": \"\u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\"}, {\"output\": \"\u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f\"})\n", "memory.save_context({\"input\": \"\u5f88\u9ad8\u5174\u548c\u4f60\u6210\u4e3a\u670b\u53cb\uff01\"}, {\"output\": \"\u662f\u7684\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u53bb\u5192\u9669\u5427\uff01\"})\n", "memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "dcabf017-5bfd-4904-9f06-388f994eddc9", "metadata": {}, "source": ["#### 3.1.2 \u5728\u5bf9\u8bdd\u94fe\u4e2d\u5e94\u7528\u7a97\u53e3\u50a8\u5b58"]}, {"cell_type": "code", "execution_count": 74, "id": "1ee854d9", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\u4f60\u597d\uff0c\u76ae\u76ae\u9c81\uff01\u5f88\u9ad8\u5174\u8ba4\u8bc6\u4f60\u3002\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u53ef\u4ee5\u56de\u7b54\u4f60\u7684\u95ee\u9898\u548c\u63d0\u4f9b\u5e2e\u52a9\u3002\u6709\u4ec0\u4e48\u6211\u53ef\u4ee5\u5e2e\u4f60\u7684\u5417\uff1f\n", "1+1\u7b49\u4e8e2\u3002\n", "\u5f88\u62b1\u6b49\uff0c\u6211\u65e0\u6cd5\u77e5\u9053\u60a8\u7684\u540d\u5b57\u3002\n"]}], "source": ["llm = ChatOpenAI(temperature=0.0)\n", "memory = ConversationBufferWindowMemory(k=1)\n", "conversation = ConversationChain(llm=llm, memory=memory, verbose=False )\n", "print(conversation.predict(input=\"\u4f60\u597d, \u6211\u53eb\u76ae\u76ae\u9c81\"))\n", "print(conversation.predict(input=\"1+1\u7b49\u4e8e\u591a\u5c11\uff1f\"))\n", "print(conversation.predict(input=\"\u6211\u53eb\u4ec0\u4e48\u540d\u5b57\uff1f\"))"]}, {"cell_type": "markdown", "id": "d2931b92", "metadata": {}, "source": ["## \u56db\u3001\u5bf9\u8bddtoken\u7f13\u5b58\u50a8\u5b58"]}, {"cell_type": "markdown", "id": "dff5b4c7", "metadata": {}, "source": ["\u4f7f\u7528\u5bf9\u8bddtoken\u7f13\u5b58\u8bb0\u5fc6\uff0c\u5185\u5b58\u5c06\u9650\u5236\u4fdd\u5b58\u7684token\u6570\u91cf\u3002\u5982\u679ctoken\u6570\u91cf\u8d85\u51fa\u6307\u5b9a\u6570\u76ee\uff0c\u5b83\u4f1a\u5207\u6389\u8fd9\u4e2a\u5bf9\u8bdd\u7684\u65e9\u671f\u90e8\u5206\n", "\u4ee5\u4fdd\u7559\u4e0e\u6700\u8fd1\u7684\u4ea4\u6d41\u76f8\u5bf9\u5e94\u7684token\u6570\u91cf\uff0c\u4f46\u4e0d\u8d85\u8fc7token\u9650\u5236\u3002"]}, {"cell_type": "code", "execution_count": 76, "id": "9f6d063c", "metadata": {"height": 31}, "outputs": [], "source": ["!pip install -q tiktoken "]}, {"cell_type": "code", "execution_count": 77, "id": "fb9020ed", "metadata": {"height": 81}, "outputs": [], "source": ["from langchain.llms import OpenAI\n", "from langchain.memory import ConversationTokenBufferMemory"]}, {"cell_type": "markdown", "id": "f3a84112", "metadata": {}, "source": ["### 4.1 \u82f1\u6587\u7248\n", "\u6dfb\u52a0\u5bf9\u8bdd\u5230Token\u7f13\u5b58\u50a8\u5b58,\u9650\u5236token\u6570\u91cf\uff0c\u8fdb\u884c\u6d4b\u8bd5"]}, {"cell_type": "code", "execution_count": 78, "id": "43582ee6", "metadata": {"height": 149}, "outputs": [], "source": ["memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", "memory.save_context({\"input\": \"AI is what?!\"}, {\"output\": \"Amazing!\"})\n", "memory.save_context({\"input\": \"Backpropagation is what?\"}, {\"output\": \"Beautiful!\"})\n", "memory.save_context({\"input\": \"Chatbots are what?\"}, {\"output\": \"Charming!\"})"]}, {"cell_type": "code", "execution_count": 79, "id": "284288e1", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["{'history': 'AI: Beautiful!\\nHuman: Chatbots are what?\\nAI: Charming!'}"]}, "execution_count": 79, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "7b62b2e1", "metadata": {}, "source": ["\u53ef\u4ee5\u770b\u5230\u524d\u9762\u8d85\u51fa\u7684\u7684token\u5df2\u7ecf\u88ab\u820d\u5f03\u4e86\uff01\uff01\uff01"]}, {"cell_type": "markdown", "id": "f7f6be43", "metadata": {}, "source": ["### 4.2 \u4e2d\u6587\u7248"]}, {"cell_type": "code", "execution_count": 80, "id": "e9191020", "metadata": {}, "outputs": [{"data": {"text/plain": ["{'history': 'AI: \u8f7b\u821f\u5df2\u8fc7\u4e07\u91cd\u5c71\u3002'}"]}, "execution_count": 80, "metadata": {}, "output_type": "execute_result"}], "source": ["memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)\n", "memory.save_context({\"input\": \"\u671d\u8f9e\u767d\u5e1d\u5f69\u4e91\u95f4\uff0c\"}, {\"output\": \"\u5343\u91cc\u6c5f\u9675\u4e00\u65e5\u8fd8\u3002\"})\n", "memory.save_context({\"input\": \"\u4e24\u5cb8\u733f\u58f0\u557c\u4e0d\u4f4f\uff0c\"}, {\"output\": \"\u8f7b\u821f\u5df2\u8fc7\u4e07\u91cd\u5c71\u3002\"})\n", "memory.load_memory_variables({})"]}, {"cell_type": "markdown", "id": "fb08ef4a-876f-422a-81f9-4805288e5955", "metadata": {}, "source": ["### 4.3 \u8865\u5145"]}, {"cell_type": "markdown", "id": "5e4d918b", "metadata": {}, "source": ["ChatGPT\u4f7f\u7528\u4e00\u79cd\u57fa\u4e8e\u5b57\u8282\u5bf9\u7f16\u7801\uff08Byte Pair Encoding\uff0cBPE\uff09\u7684\u65b9\u6cd5\u6765\u8fdb\u884ctokenization\uff08\u5c06\u8f93\u5165\u6587\u672c\u62c6\u5206\u4e3atoken\uff09\u3002BPE\u662f\u4e00\u79cd\u5e38\u89c1\u7684tokenization\u6280\u672f\uff0c\u5b83\u5c06\u8f93\u5165\u6587\u672c\u5206\u5272\u6210\u8f83\u5c0f\u7684\u5b50\u8bcd\u5355\u5143\u3002 \n", "\n", "OpenAI\u5728\u5176\u5b98\u65b9GitHub\u4e0a\u516c\u5f00\u4e86\u4e00\u4e2a\u6700\u65b0\u7684\u5f00\u6e90Python\u5e93 [tiktoken](https://github.com/openai/tiktoken)\uff0c\u8fd9\u4e2a\u5e93\u4e3b\u8981\u662f\u7528\u6765\u8ba1\u7b97tokens\u6570\u91cf\u7684\u3002\u76f8\u6bd4\u8f83HuggingFace\u7684tokenizer\uff0c\u5176\u901f\u5ea6\u63d0\u5347\u4e86\u597d\u51e0\u500d\u3002\n", "\n", "\u5177\u4f53token\u8ba1\u7b97\u65b9\u5f0f,\u7279\u522b\u662f\u6c49\u5b57\u548c\u82f1\u6587\u5355\u8bcd\u7684token\u533a\u522b\uff0c\u5177\u4f53\u8bfe\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://www.zhihu.com/question/594159910) \u3002"]}, {"cell_type": "markdown", "id": "5ff55d5d", "metadata": {}, "source": ["## \u4e94\u3001\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58"]}, {"cell_type": "markdown", "id": "7d39b83a", "metadata": {}, "source": ["\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\uff0c**\u4f7f\u7528LLM\u7f16\u5199\u5230\u76ee\u524d\u4e3a\u6b62\u5386\u53f2\u5bf9\u8bdd\u7684\u6458\u8981**\uff0c\u5e76\u5c06\u5176\u4fdd\u5b58"]}, {"cell_type": "code", "execution_count": 82, "id": "72dcf8b1", "metadata": {"height": 64}, "outputs": [], "source": ["from langchain.chains import ConversationChain\n", "from langchain.chat_models import ChatOpenAI\n", "from langchain.memory import ConversationSummaryBufferMemory"]}, {"cell_type": "markdown", "id": "243b213e-ce17-46a0-8652-03658ca58dd8", "metadata": {}, "source": ["### 5.1 \u82f1\u6587\u7248"]}, {"cell_type": "markdown", "id": "6572ef39", "metadata": {}, "source": ["#### 5.1.1 \u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\n", "\n", "\u521b\u5efa\u4e00\u4e2a\u957f\u5b57\u7b26\u4e32\uff0c\u5176\u4e2d\u5305\u542b\u67d0\u4eba\u7684\u65e5\u7a0b\u5b89\u6392"]}, {"cell_type": "code", "execution_count": 84, "id": "4a5b238f", "metadata": {"height": 285}, "outputs": [], "source": ["# \u521b\u5efa\u4e00\u4e2a\u957f\u5b57\u7b26\u4e32\n", "schedule = \"There is a meeting at 8am with your product team. \\\n", "You will need your powerpoint presentation prepared. \\\n", "9am-12pm have time to work on your LangChain \\\n", "project which will go quickly because Langchain is such a powerful tool. \\\n", "At Noon, lunch at the italian resturant with a customer who is driving \\\n", "from over an hour away to meet you to understand the latest in AI. \\\n", "Be sure to bring your laptop to show the latest LLM demo.\"\n", "\n", "# \u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u8bb0\u5fc6\n", "llm = ChatOpenAI(temperature=0.0)\n", "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100) \n", "memory.save_context({\"input\": \"Hello\"}, {\"output\": \"What's up\"})\n", "memory.save_context({\"input\": \"Not much, just hanging\"}, {\"output\": \"Cool\"})\n", "memory.save_context(\n", " {\"input\": \"What is on the schedule today?\"}, {\"output\": f\"{schedule}\"}\n", ")"]}, {"cell_type": "code", "execution_count": 89, "id": "15226a41-ab36-43a0-93f7-c03c6b374936", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n"]}], "source": ["print(memory.load_memory_variables({})['history'])"]}, {"cell_type": "markdown", "id": "7ccb97b6", "metadata": {}, "source": ["#### 5.1.2 \u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe\n", "\u57fa\u4e8e\u4e0a\u9762\u7684\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\uff0c\u65b0\u5efa\u4e00\u4e2a\u5bf9\u8bdd\u94fe"]}, {"cell_type": "code", "execution_count": 90, "id": "6728edba", "metadata": {"height": 99}, "outputs": [], "source": ["conversation = ConversationChain(llm=llm, memory=memory, verbose=True)"]}, {"cell_type": "code", "execution_count": 91, "id": "9a221b1d", "metadata": {"height": 47}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting.\n", "Human: What would be a good demo to show?\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.'"]}, "execution_count": 91, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"What would be a good demo to show?\")"]}, {"cell_type": "code", "execution_count": 92, "id": "bb582617", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["System: The human and AI exchange greetings. The human asks about the schedule for the day. The AI provides a detailed schedule, including a meeting with the product team, work on the LangChain project, and a lunch meeting with a customer interested in AI. The AI emphasizes the importance of bringing a laptop to showcase the latest LLM demo during the lunch meeting. A good demo to show during the lunch meeting with the customer interested in AI would be the latest LLM (Language Model) demo. The LLM is a cutting-edge AI model that can generate human-like text based on a given prompt. It has been trained on a vast amount of data and can generate coherent and contextually relevant responses. By showcasing the LLM demo, you can demonstrate the capabilities of AI in natural language processing and how it can be applied to various industries and use cases.\n"]}], "source": ["print(memory.load_memory_variables({})['history'])"]}, {"cell_type": "markdown", "id": "4ba827aa", "metadata": {"height": 31}, "source": ["### 5.2 \u4e2d\u6587\u7248"]}, {"cell_type": "markdown", "id": "64898f33-c538-4e68-b008-7123870b692b", "metadata": {}, "source": ["#### 5.2.1 \u4f7f\u7528\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\n", "\n", "\u521b\u5efa\u4e00\u4e2a\u957f\u5b57\u7b26\u4e32\uff0c\u5176\u4e2d\u5305\u542b\u67d0\u4eba\u7684\u65e5\u7a0b\u5b89\u6392"]}, {"cell_type": "code", "execution_count": 97, "id": "2c07922b", "metadata": {"height": 31}, "outputs": [], "source": ["# \u521b\u5efa\u4e00\u4e2a\u957f\u5b57\u7b26\u4e32\n", "schedule = \"\u5728\u516b\u70b9\u4f60\u548c\u4f60\u7684\u4ea7\u54c1\u56e2\u961f\u6709\u4e00\u4e2a\u4f1a\u8bae\u3002 \\\n", "\u4f60\u9700\u8981\u505a\u4e00\u4e2aPPT\u3002 \\\n", "\u4e0a\u53489\u70b9\u523012\u70b9\u4f60\u9700\u8981\u5fd9\u4e8eLangChain\u3002\\\n", "Langchain\u662f\u4e00\u4e2a\u6709\u7528\u7684\u5de5\u5177\uff0c\u56e0\u6b64\u4f60\u7684\u9879\u76ee\u8fdb\u5c55\u7684\u975e\u5e38\u5feb\u3002\\\n", "\u4e2d\u5348\uff0c\u5728\u610f\u5927\u5229\u9910\u5385\u4e0e\u4e00\u4f4d\u5f00\u8f66\u6765\u7684\u987e\u5ba2\u5171\u8fdb\u5348\u9910 \\\n", "\u8d70\u4e86\u4e00\u4e2a\u591a\u5c0f\u65f6\u7684\u8def\u7a0b\u4e0e\u4f60\u89c1\u9762\uff0c\u53ea\u4e3a\u4e86\u89e3\u6700\u65b0\u7684 AI\u3002 \\\n", "\u786e\u4fdd\u4f60\u5e26\u4e86\u7b14\u8bb0\u672c\u7535\u8111\u53ef\u4ee5\u5c55\u793a\u6700\u65b0\u7684 LLM \u6837\u4f8b.\"\n", "\n", "llm = ChatOpenAI(temperature=0.0)\n", "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)\n", "memory.save_context({\"input\": \"\u4f60\u597d\uff0c\u6211\u53eb\u76ae\u76ae\u9c81\"}, {\"output\": \"\u4f60\u597d\u554a\uff0c\u6211\u53eb\u9c81\u897f\u897f\"})\n", "memory.save_context({\"input\": \"\u5f88\u9ad8\u5174\u548c\u4f60\u6210\u4e3a\u670b\u53cb\uff01\"}, {\"output\": \"\u662f\u7684\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u53bb\u5192\u9669\u5427\uff01\"})\n", "memory.save_context({\"input\": \"\u4eca\u5929\u7684\u65e5\u7a0b\u5b89\u6392\u662f\u4ec0\u4e48\uff1f\"}, {\"output\": f\"{schedule}\"})"]}, {"cell_type": "code", "execution_count": 98, "id": "17424a12-430f-4529-9067-300978c6169e", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n"]}], "source": ["print(memory.load_memory_variables({})['history'])"]}, {"cell_type": "markdown", "id": "9e29a956-607a-4247-9eb5-01285a370991", "metadata": {}, "source": ["#### 5.1.2 \u57fa\u4e8e\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\u7684\u5bf9\u8bdd\u94fe\n", "\u57fa\u4e8e\u4e0a\u9762\u7684\u5bf9\u8bdd\u6458\u8981\u7f13\u5b58\u50a8\u5b58\uff0c\u65b0\u5efa\u4e00\u4e2a\u5bf9\u8bdd\u94fe"]}, {"cell_type": "code", "execution_count": 99, "id": "52696c8c", "metadata": {"height": 31}, "outputs": [], "source": ["conversation = ConversationChain(llm=llm, memory=memory, verbose=True)"]}, {"cell_type": "code", "execution_count": 100, "id": "48690d13", "metadata": {"height": 31}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "Prompt after formatting:\n", "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", "\n", "Current conversation:\n", "System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.\n", "Human: \u5c55\u793a\u4ec0\u4e48\u6837\u7684\u6837\u4f8b\u6700\u597d\u5462\uff1f\n", "AI:\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u5c55\u793a\u4e00\u4e9b\u5177\u6709\u591a\u6837\u6027\u548c\u521b\u65b0\u6027\u7684\u6837\u4f8b\u53ef\u80fd\u662f\u6700\u597d\u7684\u9009\u62e9\u3002\u4f60\u53ef\u4ee5\u9009\u62e9\u5c55\u793a\u4e00\u4e9b\u57fa\u4e8e\u56fe\u50cf\u8bc6\u522b\u7684\u6837\u4f8b\uff0c\u6bd4\u5982\u4eba\u8138\u8bc6\u522b\u3001\u7269\u4f53\u8bc6\u522b\u7b49\u3002\u53e6\u5916\uff0c\u4f60\u4e5f\u53ef\u4ee5\u5c55\u793a\u4e00\u4e9b\u81ea\u7136\u8bed\u8a00\u5904\u7406\u65b9\u9762\u7684\u6837\u4f8b\uff0c\u6bd4\u5982\u6587\u672c\u751f\u6210\u3001\u60c5\u611f\u5206\u6790\u7b49\u3002\u6700\u91cd\u8981\u7684\u662f\u9009\u62e9\u90a3\u4e9b\u80fd\u591f\u5c55\u793a\u51fa\u4f60\u4eec\u56e2\u961f\u7684\u6280\u672f\u5b9e\u529b\u548c\u521b\u9020\u529b\u7684\u6837\u4f8b\u3002'"]}, "execution_count": 100, "metadata": {}, "output_type": "execute_result"}], "source": ["conversation.predict(input=\"\u5c55\u793a\u4ec0\u4e48\u6837\u7684\u6837\u4f8b\u6700\u597d\u5462\uff1f\")"]}, {"cell_type": "code", "execution_count": 101, "id": "85bba1f8", "metadata": {"height": 31}, "outputs": [{"data": {"text/plain": ["{'history': \"System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples. The human asks what kind of samples would be best to showcase. The AI suggests that showcasing diverse and innovative samples would be the best choice. They recommend selecting samples based on image recognition, such as face recognition and object recognition. Additionally, they suggest showcasing samples related to natural language processing, such as text generation and sentiment analysis. The AI emphasizes the importance of choosing samples that demonstrate the team's technical expertise and creativity.\"}"]}, "execution_count": 101, "metadata": {}, "output_type": "execute_result"}], "source": ["memory.load_memory_variables({}) # \u6458\u8981\u8bb0\u5f55\u66f4\u65b0\u4e86"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12"}, "toc": {"base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": true}}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file From d7dc7e44dc21ea0a8d1a4a917879efa3810641b3 Mon Sep 17 00:00:00 2001 From: joyenjoye Date: Sun, 16 Jul 2023 16:27:55 +0800 Subject: [PATCH 3/5] Update Chapter 4 --- .../4.模型链 Chains.ipynb | 1732 ++++++++++++++++- 1 file changed, 1731 insertions(+), 1 deletion(-) diff --git a/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb b/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb index 7fa6440..85d6620 100644 --- a/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb +++ b/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb @@ -1 +1,1731 @@ -{"cells": [{"cell_type": "markdown", "id": "52824b89-532a-4e54-87e9-1410813cd39e", "metadata": {}, "source": ["# \u7b2c\u56db\u7ae0 \u6a21\u578b\u94fe\n", "\n", " - [\u4e00\u3001\u8bbe\u7f6eOpenAI API Key](#\u4e00\u3001\u8bbe\u7f6eOpenAI-API-Key)\n", " - [\u4e8c\u3001LLMChain](#\u4e8c\u3001LLMChain)\n", " - [\u4e09\u3001Sequential Chains](#\u4e09\u3001Sequential-Chains)\n", " - [3.1 SimpleSequentialChain](#3.1-SimpleSequentialChain)\n", " - [3.2 SequentialChain](#3.2-SequentialChain)\n", " - [\u56db\u3001 Router Chain\uff08\u8def\u7531\u94fe\uff09](#\u56db\u3001-Router-Chain\uff08\u8def\u7531\u94fe\uff09)\n", " - [4.1 \u5b9a\u4e49\u63d0\u793a\u6a21\u677f](#4.1-\u5b9a\u4e49\u63d0\u793a\u6a21\u677f)\n", " - [4.2 \u5bfc\u5165\u76f8\u5173\u7684\u5305](#4.2-\u5bfc\u5165\u76f8\u5173\u7684\u5305)\n", " - [4.3 \u5b9a\u4e49\u8bed\u8a00\u6a21\u578b](#4.3-\u5b9a\u4e49\u8bed\u8a00\u6a21\u578b)\n", " - [4.4 LLMRouterChain\uff08\u6b64\u94fe\u4f7f\u7528 LLM \u6765\u786e\u5b9a\u5982\u4f55\u8def\u7531\u4e8b\u7269\uff09](#4.4-LLMRouterChain\uff08\u6b64\u94fe\u4f7f\u7528-LLM-\u6765\u786e\u5b9a\u5982\u4f55\u8def\u7531\u4e8b\u7269\uff09)\n"]}, {"cell_type": "markdown", "id": "54810ef7", "metadata": {}, "source": ["\u94fe\u5141\u8bb8\u6211\u4eec\u5c06\u591a\u4e2a\u7ec4\u4ef6\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u4ee5\u521b\u5efa\u4e00\u4e2a\u5355\u4e00\u7684\u3001\u8fde\u8d2f\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u94fe\uff08Chains\uff09\u901a\u5e38\u5c06\u4e00\u4e2aLLM\uff08\u5927\u8bed\u8a00\u6a21\u578b\uff09\u4e0e\u63d0\u793a\u7ed3\u5408\u5728\u4e00\u8d77\uff0c\u4f7f\u7528\u8fd9\u4e2a\u6784\u5efa\u5757\uff0c\u60a8\u8fd8\u53ef\u4ee5\u5c06\u4e00\u5806\u8fd9\u4e9b\u6784\u5efa\u5757\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u5bf9\u60a8\u7684\u6587\u672c\u6216\u5176\u4ed6\u6570\u636e\u8fdb\u884c\u4e00\u7cfb\u5217\u64cd\u4f5c\u3002\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u94fe\uff0c\u8be5\u94fe\u63a5\u53d7\u7528\u6237\u8f93\u5165\uff0c\u4f7f\u7528\u63d0\u793a\u6a21\u677f\u5bf9\u5176\u8fdb\u884c\u683c\u5f0f\u5316\uff0c\u7136\u540e\u5c06\u683c\u5f0f\u5316\u7684\u54cd\u5e94\u4f20\u9012\u7ed9LLM\u3002\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u5c06\u591a\u4e2a\u94fe\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u6216\u8005\u901a\u8fc7\u5c06\u94fe\u4e0e\u5176\u4ed6\u7ec4\u4ef6\u7ec4\u5408\u5728\u4e00\u8d77\u6765\u6784\u5efa\u66f4\u590d\u6742\u7684\u94fe\u3002"]}, {"cell_type": "markdown", "id": "663fc885", "metadata": {}, "source": ["\u8fd9\u4e9b\u94fe\u7684\u4e00\u90e8\u5206\u7684\u5f3a\u5927\u4e4b\u5904\u5728\u4e8e\u4f60\u53ef\u4ee5\u4e00\u6b21\u8fd0\u884c\u5b83\u4eec\u5728\u8bb8\u591a\u8f93\u5165\u4e0a\uff0c\u56e0\u6b64\uff0c\u6211\u4eec\u5c06\u52a0\u8f7d\u4e00\u4e2apandas\u6570\u636e\u6846\u67b6"]}, {"cell_type": "markdown", "id": "21009bf6-49bd-466e-8177-74c23533d938", "metadata": {"tags": []}, "source": ["## \u4e00\u3001\u8bbe\u7f6eOpenAI API Key\n", "\n", "\u767b\u9646 [OpenAI \u8d26\u6237](https://platform.openai.com/account/api-keys) \u83b7\u53d6API Key\uff0c\u7136\u540e\u5c06\u5176\u8bbe\u7f6e\u4e3a\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u5168\u5c40\u73af\u5883\u53d8\u91cf\uff0c\u53ef\u4ee5\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://zhuanlan.zhihu.com/p/627665725)\u3002\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u672c\u5730/\u9879\u76ee\u73af\u5883\u53d8\u91cf\uff0c\u5728\u672c\u6587\u4ef6\u76ee\u5f55\u4e0b\u521b\u5efa`.env`\u6587\u4ef6, \u6253\u5f00\u6587\u4ef6\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u3002\n", "\n", "

\n", " OPENAI_API_KEY=\"your_api_key\" \n", "

\n", " \n", " \u66ff\u6362\"your_api_key\"\u4e3a\u4f60\u81ea\u5df1\u7684 API Key"]}, {"cell_type": "code", "execution_count": 1, "id": "adc3519c-4d12-4011-9223-2f3cb3c42b93", "metadata": {}, "outputs": [], "source": ["# \u4e0b\u8f7d\u9700\u8981\u7684\u5305python-dotenv\u548copenai\n", "# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "!pip install -q python-dotenv\n", "!pip install -q openai"]}, {"cell_type": "code", "execution_count": 2, "id": "1ad53241-bef6-42b8-894b-bcbbc8c64df7", "metadata": {"tags": []}, "outputs": [], "source": ["import os\n", "import openai\n", "from dotenv import load_dotenv, find_dotenv\n", "\n", "# \u8bfb\u53d6\u672c\u5730/\u9879\u76ee\u7684\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "# find_dotenv()\u5bfb\u627e\u5e76\u5b9a\u4f4d.env\u6587\u4ef6\u7684\u8def\u5f84\n", "# load_dotenv()\u8bfb\u53d6\u8be5.env\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u52a0\u8f7d\u5230\u5f53\u524d\u7684\u8fd0\u884c\u73af\u5883\u4e2d \n", "# \u5982\u679c\u4f60\u8bbe\u7f6e\u7684\u662f\u5168\u5c40\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u884c\u4ee3\u7801\u5219\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n", "_ = load_dotenv(find_dotenv())\n", "\n", "# \u83b7\u53d6\u73af\u5883\u53d8\u91cf OPENAI_API_KEY\n", "openai.api_key = os.environ['OPENAI_API_KEY'] "]}, {"cell_type": "markdown", "id": "b940ce7c", "metadata": {"tags": []}, "source": ["## \u4e8c\u3001LLMChain"]}, {"cell_type": "markdown", "id": "e000bd16", "metadata": {}, "source": ["LLMChain\u662f\u4e00\u4e2a\u7b80\u5355\u4f46\u975e\u5e38\u5f3a\u5927\u7684\u94fe\uff0c\u4e5f\u662f\u540e\u9762\u6211\u4eec\u5c06\u8981\u4ecb\u7ecd\u7684\u8bb8\u591a\u94fe\u7684\u57fa\u7840\u3002"]}, {"cell_type": "code", "execution_count": 3, "id": "b84e441b", "metadata": {}, "outputs": [], "source": ["#!pip install pandas"]}, {"cell_type": "code", "execution_count": 46, "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b", "metadata": {}, "outputs": [], "source": ["import pandas as pd\n", "df = pd.read_csv('Data.csv')"]}, {"cell_type": "code", "execution_count": 47, "id": "b7a09c35", "metadata": {}, "outputs": [{"data": {"text/html": ["
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ProductReview
0Queen Size Sheet SetI ordered a king size set. My only criticism w...
1Waterproof Phone PouchI loved the waterproof sac, although the openi...
2Luxury Air MattressThis mattress had a small hole in the top of i...
3Pillows InsertThis is the best throw pillow fillers on Amazo...
4Milk Frother Handheld\\nI loved this product. But they only seem to l...
\n", "
"], "text/plain": [" Product Review\n", "0 Queen Size Sheet Set I ordered a king size set. My only criticism w...\n", "1 Waterproof Phone Pouch I loved the waterproof sac, although the openi...\n", "2 Luxury Air Mattress This mattress had a small hole in the top of i...\n", "3 Pillows Insert This is the best throw pillow fillers on Amazo...\n", "4 Milk Frother Handheld\\n \u00a0I loved this product. But they only seem to l..."]}, "execution_count": 47, "metadata": {}, "output_type": "execute_result"}], "source": ["df.head()"]}, {"cell_type": "code", "execution_count": 48, "id": "e92dff22", "metadata": {}, "outputs": [], "source": ["from langchain.chat_models import ChatOpenAI #\u5bfc\u5165OpenAI\u6a21\u578b\n", "from langchain.prompts import ChatPromptTemplate #\u5bfc\u5165\u804a\u5929\u63d0\u793a\u6a21\u677f\n", "from langchain.chains import LLMChain #\u5bfc\u5165LLM\u94fe\u3002"]}, {"cell_type": "markdown", "id": "94a32c6f", "metadata": {}, "source": ["\u521d\u59cb\u5316\u8bed\u8a00\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 9, "id": "943237a7", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.0) #\u9884\u6d4b\u4e0b\u4e00\u4e2atoken\u65f6\uff0c\u6982\u7387\u8d8a\u5927\u7684\u503c\u5c31\u8d8a\u5e73\u6ed1(\u5e73\u6ed1\u4e5f\u5c31\u662f\u8ba9\u5dee\u5f02\u5927\u7684\u503c\u4e4b\u95f4\u7684\u5dee\u5f02\u53d8\u5f97\u6ca1\u90a3\u4e48\u5927)\uff0ctemperature\u503c\u8d8a\u5c0f\u5219\u751f\u6210\u7684\u5185\u5bb9\u8d8a\u7a33\u5b9a"]}, {"cell_type": "markdown", "id": "81887434", "metadata": {}, "source": ["\u521d\u59cb\u5316prompt\uff0c\u8fd9\u4e2aprompt\u5c06\u63a5\u53d7\u4e00\u4e2a\u540d\u4e3aproduct\u7684\u53d8\u91cf\u3002\u8be5prompt\u5c06\u8981\u6c42LLM\u751f\u6210\u4e00\u4e2a\u63cf\u8ff0\u5236\u9020\u8be5\u4ea7\u54c1\u7684\u516c\u53f8\u7684\u6700\u4f73\u540d\u79f0"]}, {"cell_type": "code", "execution_count": 7, "id": "cdcdb42d", "metadata": {}, "outputs": [], "source": ["prompt = ChatPromptTemplate.from_template( \n", " \"What is the best name to describe \\\n", " a company that makes {product}?\"\n", ")"]}, {"cell_type": "markdown", "id": "5c22cb13", "metadata": {}, "source": ["\u5c06llm\u548cprompt\u7ec4\u5408\u6210\u94fe---\u8fd9\u4e2aLLM\u94fe\u975e\u5e38\u7b80\u5355\uff0c\u4ed6\u53ea\u662fllm\u548cprompt\u7684\u7ed3\u5408\uff0c\u4f46\u662f\u73b0\u5728\uff0c\u8fd9\u4e2a\u94fe\u8ba9\u6211\u4eec\u53ef\u4ee5\u4ee5\u4e00\u79cd\u987a\u5e8f\u7684\u65b9\u5f0f\u53bb\u901a\u8fc7prompt\u8fd0\u884c\u5e76\u4e14\u7ed3\u5408\u5230LLM\u4e2d"]}, {"cell_type": "code", "execution_count": 8, "id": "d7abc20b", "metadata": {}, "outputs": [], "source": ["chain = LLMChain(llm=llm, prompt=prompt)"]}, {"cell_type": "markdown", "id": "8d7d5ff6", "metadata": {}, "source": ["\u56e0\u6b64\uff0c\u5982\u679c\u6211\u4eec\u6709\u4e00\u4e2a\u540d\u4e3a\"Queen Size Sheet Set\"\u7684\u4ea7\u54c1\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528chain.run\u5c06\u5176\u901a\u8fc7\u8fd9\u4e2a\u94fe\u8fd0\u884c"]}, {"cell_type": "code", "execution_count": 9, "id": "ad44d1fb", "metadata": {}, "outputs": [{"data": {"text/plain": ["'Royal Linens.'"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["product = \"Queen Size Sheet Set\"\n", "chain.run(product)"]}, {"cell_type": "markdown", "id": "1e1ede1c", "metadata": {}, "source": ["\u60a8\u53ef\u4ee5\u8f93\u5165\u4efb\u4f55\u4ea7\u54c1\u63cf\u8ff0\uff0c\u7136\u540e\u67e5\u770b\u94fe\u5c06\u8f93\u51fa\u4ec0\u4e48\u7ed3\u679c"]}, {"cell_type": "code", "execution_count": 14, "id": "2181be10", "metadata": {}, "outputs": [{"data": {"text/plain": ["'\"\u8c6a\u534e\u5e8a\u7eba\"'"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "prompt = ChatPromptTemplate.from_template( \n", " \"\u63cf\u8ff0\u5236\u9020{product}\u7684\u4e00\u4e2a\u516c\u53f8\u7684\u6700\u4f73\u540d\u79f0\u662f\u4ec0\u4e48?\"\n", ")\n", "chain = LLMChain(llm=llm, prompt=prompt)\n", "product = \"\u5927\u53f7\u5e8a\u5355\u5957\u88c5\"\n", "chain.run(product)"]}, {"cell_type": "markdown", "id": "49158430", "metadata": {}, "source": ["## \u4e09\u3001Sequential Chains"]}, {"cell_type": "markdown", "id": "69b03469", "metadata": {}, "source": ["### 3.1 SimpleSequentialChain\n", "\n", "\u987a\u5e8f\u94fe\uff08Sequential Chains\uff09\u662f\u6309\u9884\u5b9a\u4e49\u987a\u5e8f\u6267\u884c\u5176\u94fe\u63a5\u7684\u94fe\u3002\u5177\u4f53\u6765\u8bf4\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u7b80\u5355\u987a\u5e8f\u94fe\uff08SimpleSequentialChain\uff09\uff0c\u8fd9\u662f\u987a\u5e8f\u94fe\u7684\u6700\u7b80\u5355\u7c7b\u578b\uff0c\u5176\u4e2d\u6bcf\u4e2a\u6b65\u9aa4\u90fd\u6709\u4e00\u4e2a\u8f93\u5165/\u8f93\u51fa\uff0c\u4e00\u4e2a\u6b65\u9aa4\u7684\u8f93\u51fa\u662f\u4e0b\u4e00\u4e2a\u6b65\u9aa4\u7684\u8f93\u5165"]}, {"cell_type": "code", "execution_count": 15, "id": "febee243", "metadata": {}, "outputs": [], "source": ["from langchain.chains import SimpleSequentialChain"]}, {"cell_type": "code", "execution_count": 16, "id": "5d019d6f", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.9)"]}, {"cell_type": "markdown", "id": "0e732589", "metadata": {}, "source": ["\u5b50\u94fe 1"]}, {"cell_type": "code", "execution_count": 15, "id": "2f31aa8a", "metadata": {}, "outputs": [], "source": ["\n", "# \u63d0\u793a\u6a21\u677f 1 \uff1a\u8fd9\u4e2a\u63d0\u793a\u5c06\u63a5\u53d7\u4ea7\u54c1\u5e76\u8fd4\u56de\u6700\u4f73\u540d\u79f0\u6765\u63cf\u8ff0\u8be5\u516c\u53f8\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"What is the best name to describe \\\n", " a company that makes {product}?\"\n", ")\n", "\n", "# Chain 1\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt)"]}, {"cell_type": "markdown", "id": "dcfca7bd", "metadata": {}, "source": ["\u5b50\u94fe 2"]}, {"cell_type": "code", "execution_count": 16, "id": "3f5d5b76", "metadata": {}, "outputs": [], "source": ["\n", "# \u63d0\u793a\u6a21\u677f 2 \uff1a\u63a5\u53d7\u516c\u53f8\u540d\u79f0\uff0c\u7136\u540e\u8f93\u51fa\u8be5\u516c\u53f8\u7684\u957f\u4e3a20\u4e2a\u5355\u8bcd\u7684\u63cf\u8ff0\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"Write a 20 words description for the following \\\n", " company:{company_name}\"\n", ")\n", "# chain 2\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt)"]}, {"cell_type": "markdown", "id": "3a1991f4", "metadata": {}, "source": ["\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u7ec4\u5408\u4e24\u4e2aLLMChain\uff0c\u4ee5\u4fbf\u6211\u4eec\u53ef\u4ee5\u5728\u4e00\u4e2a\u6b65\u9aa4\u4e2d\u521b\u5efa\u516c\u53f8\u540d\u79f0\u548c\u63cf\u8ff0"]}, {"cell_type": "code", "execution_count": 17, "id": "6c1eb2c4", "metadata": {}, "outputs": [], "source": ["overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],\n", " verbose=True\n", " )"]}, {"cell_type": "markdown", "id": "5122f26a", "metadata": {}, "source": ["\u7ed9\u4e00\u4e2a\u8f93\u5165\uff0c\u7136\u540e\u8fd0\u884c\u4e0a\u9762\u7684\u94fe"]}, {"cell_type": "code", "execution_count": 18, "id": "78458efe", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", "\u001b[36;1m\u001b[1;3mRoyal Linens\u001b[0m\n", "\u001b[33;1m\u001b[1;3mRoyal Linens is a high-quality bedding and linen company that offers luxurious and stylish products for comfortable living.\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Royal Linens is a high-quality bedding and linen company that offers luxurious and stylish products for comfortable living.'"]}, "execution_count": 18, "metadata": {}, "output_type": "execute_result"}], "source": ["product = \"Queen Size Sheet Set\"\n", "overall_simple_chain.run(product)"]}, {"cell_type": "code", "execution_count": 19, "id": "c7c32997", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", "\u001b[36;1m\u001b[1;3m\"\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\"\u001b[0m\n", "\u001b[33;1m\u001b[1;3m\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\u662f\u4e00\u5bb6\u4e13\u6ce8\u4e8e\u5e8a\u4e0a\u7528\u54c1\u751f\u4ea7\u7684\u516c\u53f8\u3002\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\u662f\u4e00\u5bb6\u4e13\u6ce8\u4e8e\u5e8a\u4e0a\u7528\u54c1\u751f\u4ea7\u7684\u516c\u53f8\u3002'"]}, "execution_count": 19, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "\n", "first_prompt = ChatPromptTemplate.from_template( \n", " \"\u63cf\u8ff0\u5236\u9020{product}\u7684\u4e00\u4e2a\u516c\u53f8\u7684\u6700\u597d\u7684\u540d\u79f0\u662f\u4ec0\u4e48\"\n", ")\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt)\n", "\n", "second_prompt = ChatPromptTemplate.from_template( \n", " \"\u5199\u4e00\u4e2a20\u5b57\u7684\u63cf\u8ff0\u5bf9\u4e8e\u4e0b\u9762\u8fd9\u4e2a\\\n", " \u516c\u53f8\uff1a{company_name}\u7684\"\n", ")\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt)\n", "\n", "\n", "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],\n", " verbose=True\n", " )\n", "product = \"\u5927\u53f7\u5e8a\u5355\u5957\u88c5\"\n", "overall_simple_chain.run(product)"]}, {"cell_type": "markdown", "id": "7b5ce18c", "metadata": {}, "source": ["### 3.2 SequentialChain"]}, {"cell_type": "markdown", "id": "1e69f4c0", "metadata": {}, "source": ["\u5f53\u53ea\u6709\u4e00\u4e2a\u8f93\u5165\u548c\u4e00\u4e2a\u8f93\u51fa\u65f6\uff0c\u7b80\u5355\u7684\u987a\u5e8f\u94fe\u53ef\u4ee5\u987a\u5229\u5b8c\u6210\u3002\u4f46\u662f\u5f53\u6709\u591a\u4e2a\u8f93\u5165\u6216\u591a\u4e2a\u8f93\u51fa\u65f6\u8be5\u5982\u4f55\u5b9e\u73b0\u5462\uff1f\n", "\n", "\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u666e\u901a\u7684\u987a\u5e8f\u94fe\u6765\u5b9e\u73b0\u8fd9\u4e00\u70b9"]}, {"cell_type": "code", "execution_count": 1, "id": "4c129ef6", "metadata": {}, "outputs": [], "source": ["from langchain.chains import SequentialChain\n", "from langchain.chat_models import ChatOpenAI #\u5bfc\u5165OpenAI\u6a21\u578b\n", "from langchain.prompts import ChatPromptTemplate #\u5bfc\u5165\u804a\u5929\u63d0\u793a\u6a21\u677f\n", "from langchain.chains import LLMChain #\u5bfc\u5165LLM\u94fe\u3002"]}, {"cell_type": "markdown", "id": "3d4be4e8", "metadata": {}, "source": ["\u521d\u59cb\u5316\u8bed\u8a00\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 2, "id": "03a8e203", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.9)"]}, {"cell_type": "markdown", "id": "9811445c", "metadata": {}, "source": ["\u63a5\u4e0b\u6765\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u7cfb\u5217\u7684\u94fe\uff0c\u7136\u540e\u4e00\u4e2a\u63a5\u4e00\u4e2a\u4f7f\u7528\u4ed6\u4eec"]}, {"cell_type": "code", "execution_count": 23, "id": "016187ac", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe1\n", "\n", "# prompt\u6a21\u677f 1: \u7ffb\u8bd1\u6210\u82f1\u8bed\uff08\u628a\u4e0b\u9762\u7684review\u7ffb\u8bd1\u6210\u82f1\u8bed\uff09\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"Translate the following review to english:\"\n", " \"\\n\\n{Review}\"\n", ")\n", "# chain 1: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a \u82f1\u6587\u7684 Review\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt, \n", " output_key=\"English_Review\"\n", " )\n"]}, {"cell_type": "code", "execution_count": 25, "id": "0fb0730e", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe2\n", "\n", "# prompt\u6a21\u677f 2: \u7528\u4e00\u53e5\u8bdd\u603b\u7ed3\u4e0b\u9762\u7684 review\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"Can you summarize the following review in 1 sentence:\"\n", " \"\\n\\n{English_Review}\"\n", ")\n", "# chain 2: \u8f93\u5165\uff1a\u82f1\u6587\u7684Review \u8f93\u51fa\uff1a\u603b\u7ed3\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt, \n", " output_key=\"summary\"\n", " )\n"]}, {"cell_type": "code", "execution_count": 26, "id": "6accf92d", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe3\n", "\n", "# prompt\u6a21\u677f 3: \u4e0b\u9762review\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00\n", "third_prompt = ChatPromptTemplate.from_template(\n", " \"What language is the following review:\\n\\n{Review}\"\n", ")\n", "# chain 3: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u8bed\u8a00\n", "chain_three = LLMChain(llm=llm, prompt=third_prompt,\n", " output_key=\"language\"\n", " )\n"]}, {"cell_type": "code", "execution_count": 27, "id": "c7a46121", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe4\n", "\n", "# prompt\u6a21\u677f 4: \u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d\n", "fourth_prompt = ChatPromptTemplate.from_template(\n", " \"Write a follow up response to the following \"\n", " \"summary in the specified language:\"\n", " \"\\n\\nSummary: {summary}\\n\\nLanguage: {language}\"\n", ")\n", "# chain 4: \u8f93\u5165\uff1a \u603b\u7ed3, \u8bed\u8a00 \u8f93\u51fa\uff1a \u540e\u7eed\u56de\u590d\n", "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n", " output_key=\"followup_message\"\n", " )\n"]}, {"cell_type": "code", "execution_count": 28, "id": "89603117", "metadata": {}, "outputs": [], "source": ["# \u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408\n", "\n", "#\u8f93\u5165\uff1areview \u8f93\u51fa\uff1a\u82f1\u6587review\uff0c\u603b\u7ed3\uff0c\u540e\u7eed\u56de\u590d \n", "overall_chain = SequentialChain(\n", " chains=[chain_one, chain_two, chain_three, chain_four],\n", " input_variables=[\"Review\"],\n", " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", " verbose=True\n", ")"]}, {"cell_type": "markdown", "id": "0509de01", "metadata": {}, "source": ["\u8ba9\u6211\u4eec\u9009\u62e9\u4e00\u7bc7\u8bc4\u8bba\u5e76\u901a\u8fc7\u6574\u4e2a\u94fe\u4f20\u9012\u5b83\uff0c\u53ef\u4ee5\u53d1\u73b0\uff0c\u539f\u59cbreview\u662f\u6cd5\u8bed\uff0c\u53ef\u4ee5\u628a\u82f1\u6587review\u770b\u505a\u662f\u4e00\u79cd\u7ffb\u8bd1\uff0c\u63a5\u4e0b\u6765\u662f\u6839\u636e\u82f1\u6587review\u5f97\u5230\u7684\u603b\u7ed3\uff0c\u6700\u540e\u8f93\u51fa\u7684\u662f\u7528\u6cd5\u8bed\u539f\u6587\u8fdb\u884c\u7684\u7eed\u5199\u4fe1\u606f\u3002"]}, {"cell_type": "code", "execution_count": 12, "id": "51b04f45", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new SequentialChain chain...\u001b[0m\n"]}, {"name": "stderr", "output_type": "stream", "text": ["Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 2.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 8.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n"]}, {"name": "stdout", "output_type": "stream", "text": ["\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["{'Review': \"Je trouve le go\u00fbt m\u00e9diocre. La mousse ne tient pas, c'est bizarre. J'ach\u00e8te les m\u00eames dans le commerce et le go\u00fbt est bien meilleur...\\nVieux lot ou contrefa\u00e7on !?\",\n", " 'English_Review': '\"I find the taste mediocre. The foam doesn\\'t hold, it\\'s weird. I buy the same ones in stores and the taste is much better... Old batch or counterfeit!?\"',\n", " 'summary': \"The taste is mediocre, the foam doesn't hold and the reviewer suspects it's either an old batch or counterfeit.\",\n", " 'followup_message': \"R\u00e9ponse : La saveur est moyenne, la mousse ne tient pas et le critique soup\u00e7onne qu'il s'agit soit d'un lot p\u00e9rim\u00e9, soit d'une contrefa\u00e7on. Il est important de prendre en compte les commentaires des clients pour am\u00e9liorer notre produit. Nous allons enqu\u00eater sur cette question plus en d\u00e9tail pour nous assurer que nos produits sont de la plus haute qualit\u00e9 possible. Nous esp\u00e9rons que vous nous donnerez une autre chance \u00e0 l'avenir. Merci d'avoir pris le temps de nous donner votre avis sinc\u00e8re.\"}"]}, "execution_count": 12, "metadata": {}, "output_type": "execute_result"}], "source": ["review = df.Review[5]\n", "overall_chain(review)"]}, {"cell_type": "code", "execution_count": 9, "id": "31624a7c", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new SequentialChain chain...\u001b[0m\n"]}, {"name": "stderr", "output_type": "stream", "text": ["Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 2.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n", "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 8.0 seconds as it raised RateLimitError: Rate limit reached for default-gpt-3.5-turbo in organization org-kmMHlitaQynVMwTW3jDTCPga on requests per min. Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to have issues. Please add a payment method to your account to increase your rate limit. Visit https://platform.openai.com/account/billing to add a payment method..\n"]}, {"name": "stdout", "output_type": "stream", "text": ["\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["{'Review': \"Je trouve le go\u00fbt m\u00e9diocre. La mousse ne tient pas, c'est bizarre. J'ach\u00e8te les m\u00eames dans le commerce et le go\u00fbt est bien meilleur...\\nVieux lot ou contrefa\u00e7on !?\",\n", " 'English_Review': \"I find the taste mediocre. The foam doesn't last, it's strange. I buy the same ones in stores and the taste is much better...\\nOld batch or counterfeit?!\",\n", " 'summary': \"The reviewer finds the taste mediocre and suspects that either the product is from an old batch or it might be counterfeit, as the foam doesn't last and the taste is not as good as the ones purchased in stores.\",\n", " 'followup_message': \"\u540e\u7eed\u56de\u590d: Bonjour! Je vous remercie de votre commentaire concernant notre produit. Nous sommes d\u00e9sol\u00e9s d'apprendre que vous avez trouv\u00e9 le go\u00fbt moyen et que vous soup\u00e7onnez qu'il s'agit peut-\u00eatre d'un ancien lot ou d'une contrefa\u00e7on, car la mousse ne dure pas et le go\u00fbt n'est pas aussi bon que ceux achet\u00e9s en magasin. Nous appr\u00e9cions vos pr\u00e9occupations et nous aimerions enqu\u00eater davantage sur cette situation. Pourriez-vous s'il vous pla\u00eet nous fournir plus de d\u00e9tails, tels que la date d'achat et le num\u00e9ro de lot du produit? Nous sommes d\u00e9termin\u00e9s \u00e0 offrir la meilleure qualit\u00e9 \u00e0 nos clients et nous ferons tout notre possible pour r\u00e9soudre ce probl\u00e8me. Merci encore pour votre commentaire et nous attendons votre r\u00e9ponse avec impatience. Cordialement.\"}"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "\n", "#\u5b50\u94fe1\n", "\n", "# prompt\u6a21\u677f 1: \u7ffb\u8bd1\u6210\u82f1\u8bed\uff08\u628a\u4e0b\u9762\u7684review\u7ffb\u8bd1\u6210\u82f1\u8bed\uff09\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"\u628a\u4e0b\u9762\u7684\u8bc4\u8bbareview\u7ffb\u8bd1\u6210\u82f1\u6587:\"\n", " \"\\n\\n{Review}\"\n", ")\n", "# chain 1: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u82f1\u6587\u7684 Review\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt, \n", " output_key=\"English_Review\"\n", " )\n", "\n", "#\u5b50\u94fe2\n", "\n", "# prompt\u6a21\u677f 2: \u7528\u4e00\u53e5\u8bdd\u603b\u7ed3\u4e0b\u9762\u7684 review\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"\u8bf7\u4f60\u7528\u4e00\u53e5\u8bdd\u6765\u603b\u7ed3\u4e0b\u9762\u7684\u8bc4\u8bbareview:\"\n", " \"\\n\\n{English_Review}\"\n", ")\n", "# chain 2: \u8f93\u5165\uff1a\u82f1\u6587\u7684Review \u8f93\u51fa\uff1a\u603b\u7ed3\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt, \n", " output_key=\"summary\"\n", " )\n", "\n", "\n", "#\u5b50\u94fe3\n", "\n", "# prompt\u6a21\u677f 3: \u4e0b\u9762review\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00\n", "third_prompt = ChatPromptTemplate.from_template(\n", " \"\u4e0b\u9762\u7684\u8bc4\u8bbareview\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00:\\n\\n{Review}\"\n", ")\n", "# chain 3: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u8bed\u8a00\n", "chain_three = LLMChain(llm=llm, prompt=third_prompt,\n", " output_key=\"language\"\n", " )\n", "\n", "\n", "#\u5b50\u94fe4\n", "\n", "# prompt\u6a21\u677f 4: \u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d\n", "fourth_prompt = ChatPromptTemplate.from_template(\n", " \"\u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d:\"\n", " \"\\n\\n\u603b\u7ed3: {summary}\\n\\n\u8bed\u8a00: {language}\"\n", ")\n", "# chain 4: \u8f93\u5165\uff1a \u603b\u7ed3, \u8bed\u8a00 \u8f93\u51fa\uff1a \u540e\u7eed\u56de\u590d\n", "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n", " output_key=\"followup_message\"\n", " )\n", "\n", "\n", "# \u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408\n", "\n", "#\u8f93\u5165\uff1areview \u8f93\u51fa\uff1a\u82f1\u6587review\uff0c\u603b\u7ed3\uff0c\u540e\u7eed\u56de\u590d \n", "overall_chain = SequentialChain(\n", " chains=[chain_one, chain_two, chain_three, chain_four],\n", " input_variables=[\"Review\"],\n", " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", " verbose=True\n", ")\n", "\n", "\n", "review = df.Review[5]\n", "overall_chain(review)"]}, {"cell_type": "markdown", "id": "3041ea4c", "metadata": {}, "source": ["## \u56db\u3001 Router Chain\uff08\u8def\u7531\u94fe\uff09"]}, {"cell_type": "markdown", "id": "f0c32f97", "metadata": {}, "source": ["\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5df2\u7ecf\u5b66\u4e60\u4e86LLM\u94fe\u548c\u987a\u5e8f\u94fe\u3002\u4f46\u662f\uff0c\u5982\u679c\u60a8\u60f3\u505a\u4e00\u4e9b\u66f4\u590d\u6742\u7684\u4e8b\u60c5\u600e\u4e48\u529e\uff1f\n", "\n", "\u4e00\u4e2a\u76f8\u5f53\u5e38\u89c1\u4f46\u57fa\u672c\u7684\u64cd\u4f5c\u662f\u6839\u636e\u8f93\u5165\u5c06\u5176\u8def\u7531\u5230\u4e00\u6761\u94fe\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u8be5\u8f93\u5165\u5230\u5e95\u662f\u4ec0\u4e48\u3002\u5982\u679c\u4f60\u6709\u591a\u4e2a\u5b50\u94fe\uff0c\u6bcf\u4e2a\u5b50\u94fe\u90fd\u4e13\u95e8\u7528\u4e8e\u7279\u5b9a\u7c7b\u578b\u7684\u8f93\u5165\uff0c\u90a3\u4e48\u53ef\u4ee5\u7ec4\u6210\u4e00\u4e2a\u8def\u7531\u94fe\uff0c\u5b83\u9996\u5148\u51b3\u5b9a\u5c06\u5b83\u4f20\u9012\u7ed9\u54ea\u4e2a\u5b50\u94fe\uff0c\u7136\u540e\u5c06\u5b83\u4f20\u9012\u7ed9\u90a3\u4e2a\u94fe\u3002\n", "\n", "\u8def\u7531\u5668\u7531\u4e24\u4e2a\u7ec4\u4ef6\u7ec4\u6210\uff1a\n", "\n", "- \u8def\u7531\u5668\u94fe\u672c\u8eab\uff08\u8d1f\u8d23\u9009\u62e9\u8981\u8c03\u7528\u7684\u4e0b\u4e00\u4e2a\u94fe\uff09\n", "- destination_chains\uff1a\u8def\u7531\u5668\u94fe\u53ef\u4ee5\u8def\u7531\u5230\u7684\u94fe\n", "\n", "\u4e3e\u4e00\u4e2a\u5177\u4f53\u7684\u4f8b\u5b50\uff0c\u8ba9\u6211\u4eec\u770b\u4e00\u4e0b\u6211\u4eec\u5728\u4e0d\u540c\u7c7b\u578b\u7684\u94fe\u4e4b\u95f4\u8def\u7531\u7684\u5730\u65b9\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u6709\u4e0d\u540c\u7684prompt: "]}, {"cell_type": "markdown", "id": "cb1b4708", "metadata": {}, "source": ["### 4.1 \u5b9a\u4e49\u63d0\u793a\u6a21\u677f"]}, {"cell_type": "code", "execution_count": 49, "id": "ade83f4f", "metadata": {}, "outputs": [], "source": ["#\u7b2c\u4e00\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u7269\u7406\u95ee\u9898\n", "physics_template = \"\"\"You are a very smart physics professor. \\\n", "You are great at answering questions about physics in a concise\\\n", "and easy to understand manner. \\\n", "When you don't know the answer to a question you admit\\\n", "that you don't know.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e8c\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u6570\u5b66\u95ee\u9898\n", "math_template = \"\"\"You are a very good mathematician. \\\n", "You are great at answering math questions. \\\n", "You are so good because you are able to break down \\\n", "hard problems into their component parts, \n", "answer the component parts, and then put them together\\\n", "to answer the broader question.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e09\u4e2a\u9002\u5408\u56de\u7b54\u5386\u53f2\u95ee\u9898\n", "history_template = \"\"\"You are a very good historian. \\\n", "You have an excellent knowledge of and understanding of people,\\\n", "events and contexts from a range of historical periods. \\\n", "You have the ability to think, reflect, debate, discuss and \\\n", "evaluate the past. You have a respect for historical evidence\\\n", "and the ability to make use of it to support your explanations \\\n", "and judgements.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u56db\u4e2a\u9002\u5408\u56de\u7b54\u8ba1\u7b97\u673a\u95ee\u9898\n", "computerscience_template = \"\"\" You are a successful computer scientist.\\\n", "You have a passion for creativity, collaboration,\\\n", "forward-thinking, confidence, strong problem-solving capabilities,\\\n", "understanding of theories and algorithms, and excellent communication \\\n", "skills. You are great at answering coding questions. \\\n", "You are so good because you know how to solve a problem by \\\n", "describing the solution in imperative steps \\\n", "that a machine can easily interpret and you know how to \\\n", "choose a solution that has a good balance between \\\n", "time complexity and space complexity. \n", "\n", "Here is a question:\n", "{input}\"\"\""]}, {"cell_type": "code", "execution_count": 51, "id": "f7fade7a", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "#\u7b2c\u4e00\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u7269\u7406\u95ee\u9898\n", "physics_template = \"\"\"\u4f60\u662f\u4e00\u4e2a\u975e\u5e38\u806a\u660e\u7684\u7269\u7406\u4e13\u5bb6\u3002 \\\n", "\u4f60\u64c5\u957f\u7528\u4e00\u79cd\u7b80\u6d01\u5e76\u4e14\u6613\u4e8e\u7406\u89e3\u7684\u65b9\u5f0f\u53bb\u56de\u7b54\u95ee\u9898\u3002\\\n", "\u5f53\u4f60\u4e0d\u77e5\u9053\u95ee\u9898\u7684\u7b54\u6848\u65f6\uff0c\u4f60\u627f\u8ba4\\\n", "\u4f60\u4e0d\u77e5\u9053.\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e8c\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u6570\u5b66\u95ee\u9898\n", "math_template = \"\"\"\u4f60\u662f\u4e00\u4e2a\u975e\u5e38\u4f18\u79c0\u7684\u6570\u5b66\u5bb6\u3002 \\\n", "\u4f60\u64c5\u957f\u56de\u7b54\u6570\u5b66\u95ee\u9898\u3002 \\\n", "\u4f60\u4e4b\u6240\u4ee5\u5982\u6b64\u4f18\u79c0\uff0c \\\n", "\u662f\u56e0\u4e3a\u4f60\u80fd\u591f\u5c06\u68d8\u624b\u7684\u95ee\u9898\u5206\u89e3\u4e3a\u7ec4\u6210\u90e8\u5206\uff0c\\\n", "\u56de\u7b54\u7ec4\u6210\u90e8\u5206\uff0c\u7136\u540e\u5c06\u5b83\u4eec\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u56de\u7b54\u66f4\u5e7f\u6cdb\u7684\u95ee\u9898\u3002\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898\uff1a\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e09\u4e2a\u9002\u5408\u56de\u7b54\u5386\u53f2\u95ee\u9898\n", "history_template = \"\"\"\u4f60\u662f\u4ee5\u4e3a\u975e\u5e38\u4f18\u79c0\u7684\u5386\u53f2\u5b66\u5bb6\u3002 \\\n", "\u4f60\u5bf9\u4e00\u7cfb\u5217\u5386\u53f2\u65f6\u671f\u7684\u4eba\u7269\u3001\u4e8b\u4ef6\u548c\u80cc\u666f\u6709\u7740\u6781\u597d\u7684\u5b66\u8bc6\u548c\u7406\u89e3\\\n", "\u4f60\u6709\u80fd\u529b\u601d\u8003\u3001\u53cd\u601d\u3001\u8fa9\u8bc1\u3001\u8ba8\u8bba\u548c\u8bc4\u4f30\u8fc7\u53bb\u3002\\\n", "\u4f60\u5c0a\u91cd\u5386\u53f2\u8bc1\u636e\uff0c\u5e76\u6709\u80fd\u529b\u5229\u7528\u5b83\u6765\u652f\u6301\u4f60\u7684\u89e3\u91ca\u548c\u5224\u65ad\u3002\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u56db\u4e2a\u9002\u5408\u56de\u7b54\u8ba1\u7b97\u673a\u95ee\u9898\n", "computerscience_template = \"\"\" \u4f60\u662f\u4e00\u4e2a\u6210\u529f\u7684\u8ba1\u7b97\u673a\u79d1\u5b66\u4e13\u5bb6\u3002\\\n", "\u4f60\u6709\u521b\u9020\u529b\u3001\u534f\u4f5c\u7cbe\u795e\u3001\\\n", "\u524d\u77bb\u6027\u601d\u7ef4\u3001\u81ea\u4fe1\u3001\u89e3\u51b3\u95ee\u9898\u7684\u80fd\u529b\u3001\\\n", "\u5bf9\u7406\u8bba\u548c\u7b97\u6cd5\u7684\u7406\u89e3\u4ee5\u53ca\u51fa\u8272\u7684\u6c9f\u901a\u6280\u5de7\u3002\\\n", "\u4f60\u975e\u5e38\u64c5\u957f\u56de\u7b54\u7f16\u7a0b\u95ee\u9898\u3002\\\n", "\u4f60\u4e4b\u6240\u4ee5\u5982\u6b64\u4f18\u79c0\uff0c\u662f\u56e0\u4e3a\u4f60\u77e5\u9053 \\\n", "\u5982\u4f55\u901a\u8fc7\u4ee5\u673a\u5668\u53ef\u4ee5\u8f7b\u677e\u89e3\u91ca\u7684\u547d\u4ee4\u5f0f\u6b65\u9aa4\u63cf\u8ff0\u89e3\u51b3\u65b9\u6848\u6765\u89e3\u51b3\u95ee\u9898\uff0c\\\n", "\u5e76\u4e14\u4f60\u77e5\u9053\u5982\u4f55\u9009\u62e9\u5728\u65f6\u95f4\u590d\u6742\u6027\u548c\u7a7a\u95f4\u590d\u6742\u6027\u4e4b\u95f4\u53d6\u5f97\u826f\u597d\u5e73\u8861\u7684\u89e3\u51b3\u65b9\u6848\u3002\n", "\n", "\u8fd9\u8fd8\u662f\u4e00\u4e2a\u8f93\u5165\uff1a\n", "{input}\"\"\""]}, {"cell_type": "markdown", "id": "6922b35e", "metadata": {}, "source": ["\u9996\u5148\u9700\u8981\u5b9a\u4e49\u8fd9\u4e9b\u63d0\u793a\u6a21\u677f\uff0c\u5728\u6211\u4eec\u62e5\u6709\u4e86\u8fd9\u4e9b\u63d0\u793a\u6a21\u677f\u540e\uff0c\u53ef\u4ee5\u4e3a\u6bcf\u4e2a\u6a21\u677f\u547d\u540d\uff0c\u7136\u540e\u63d0\u4f9b\u63cf\u8ff0\u3002\u4f8b\u5982\uff0c\u7b2c\u4e00\u4e2a\u7269\u7406\u5b66\u7684\u63cf\u8ff0\u9002\u5408\u56de\u7b54\u5173\u4e8e\u7269\u7406\u5b66\u7684\u95ee\u9898\uff0c\u8fd9\u4e9b\u4fe1\u606f\u5c06\u4f20\u9012\u7ed9\u8def\u7531\u94fe\uff0c\u7136\u540e\u7531\u8def\u7531\u94fe\u51b3\u5b9a\u4f55\u65f6\u4f7f\u7528\u6b64\u5b50\u94fe\u3002"]}, {"cell_type": "code", "execution_count": 27, "id": "141a3d32", "metadata": {}, "outputs": [], "source": ["prompt_infos = [\n", " {\n", " \"name\": \"physics\", \n", " \"description\": \"Good for answering questions about physics\", \n", " \"prompt_template\": physics_template\n", " },\n", " {\n", " \"name\": \"math\", \n", " \"description\": \"Good for answering math questions\", \n", " \"prompt_template\": math_template\n", " },\n", " {\n", " \"name\": \"History\", \n", " \"description\": \"Good for answering history questions\", \n", " \"prompt_template\": history_template\n", " },\n", " {\n", " \"name\": \"computer science\", \n", " \"description\": \"Good for answering computer science questions\", \n", " \"prompt_template\": computerscience_template\n", " }\n", "]"]}, {"cell_type": "code", "execution_count": 52, "id": "deb8aafc", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "prompt_infos = [\n", " {\n", " \"\u540d\u5b57\": \"\u7269\u7406\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u5173\u4e8e\u7269\u7406\u5b66\u7684\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": physics_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u6570\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u6570\u5b66\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": math_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u5386\u53f2\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u5386\u53f2\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": history_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u8ba1\u7b97\u673a\u79d1\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u8ba1\u7b97\u673a\u79d1\u5b66\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": computerscience_template\n", " }\n", "]\n"]}, {"cell_type": "markdown", "id": "80eb1de8", "metadata": {}, "source": ["### 4.2 \u5bfc\u5165\u76f8\u5173\u7684\u5305"]}, {"cell_type": "code", "execution_count": 28, "id": "31b06fc8", "metadata": {}, "outputs": [], "source": ["from langchain.chains.router import MultiPromptChain #\u5bfc\u5165\u591a\u63d0\u793a\u94fe\n", "from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser\n", "from langchain.prompts import PromptTemplate"]}, {"cell_type": "markdown", "id": "50c16f01", "metadata": {}, "source": ["### 4.3 \u5b9a\u4e49\u8bed\u8a00\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 29, "id": "f3f50bcc", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0)"]}, {"cell_type": "markdown", "id": "8795cd42", "metadata": {}, "source": ["### 4.4 LLMRouterChain\uff08\u6b64\u94fe\u4f7f\u7528 LLM \u6765\u786e\u5b9a\u5982\u4f55\u8def\u7531\u4e8b\u7269\uff09\n", "\n", "\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u9700\u8981\u4e00\u4e2a**\u591a\u63d0\u793a\u94fe**\u3002\u8fd9\u662f\u4e00\u79cd\u7279\u5b9a\u7c7b\u578b\u7684\u94fe\uff0c\u7528\u4e8e\u5728\u591a\u4e2a\u4e0d\u540c\u7684\u63d0\u793a\u6a21\u677f\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002\n", "\u4f46\u662f\uff0c\u8fd9\u53ea\u662f\u4f60\u53ef\u4ee5\u8def\u7531\u7684\u4e00\u79cd\u7c7b\u578b\u3002\u4f60\u4e5f\u53ef\u4ee5\u5728\u4efb\u4f55\u7c7b\u578b\u7684\u94fe\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002\n", "\n", "\u8fd9\u91cc\u6211\u4eec\u8981\u5b9e\u73b0\u7684\u51e0\u4e2a\u7c7b\u662fLLM\u8def\u7531\u5668\u94fe\u3002\u8fd9\u4e2a\u7c7b\u672c\u8eab\u4f7f\u7528\u8bed\u8a00\u6a21\u578b\u6765\u5728\u4e0d\u540c\u7684\u5b50\u94fe\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002\n", "\u8fd9\u5c31\u662f\u4e0a\u9762\u63d0\u4f9b\u7684\u63cf\u8ff0\u548c\u540d\u79f0\u5c06\u88ab\u4f7f\u7528\u7684\u5730\u65b9\u3002"]}, {"cell_type": "markdown", "id": "46633b43", "metadata": {}, "source": ["#### 4.4.1 \u521b\u5efa\u76ee\u6807\u94fe \n", "\u76ee\u6807\u94fe\u662f\u7531\u8def\u7531\u94fe\u8c03\u7528\u7684\u94fe\uff0c\u6bcf\u4e2a\u76ee\u6807\u94fe\u90fd\u662f\u4e00\u4e2a\u8bed\u8a00\u6a21\u578b\u94fe"]}, {"cell_type": "code", "execution_count": 30, "id": "8eefec24", "metadata": {}, "outputs": [], "source": ["destination_chains = {}\n", "for p_info in prompt_infos:\n", " name = p_info[\"name\"]\n", " prompt_template = p_info[\"prompt_template\"]\n", " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", " chain = LLMChain(llm=llm, prompt=prompt)\n", " destination_chains[name] = chain \n", " \n", "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n", "destinations_str = \"\\n\".join(destinations)"]}, {"cell_type": "code", "execution_count": null, "id": "fd6eb641", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "destination_chains = {}\n", "for p_info in prompt_infos:\n", " name = p_info[\"\u540d\u5b57\"]\n", " prompt_template = p_info[\"\u63d0\u793a\u6a21\u677f\"]\n", " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", " chain = LLMChain(llm=llm, prompt=prompt)\n", " destination_chains[name] = chain \n", " \n", "destinations = [f\"{p['\u540d\u5b57']}: {p['\u63cf\u8ff0']}\" for p in prompt_infos]\n", "destinations_str = \"\\n\".join(destinations)"]}, {"cell_type": "markdown", "id": "eba115de", "metadata": {}, "source": ["#### 4.4.2 \u521b\u5efa\u9ed8\u8ba4\u76ee\u6807\u94fe\n", "\u9664\u4e86\u76ee\u6807\u94fe\u4e4b\u5916\uff0c\u6211\u4eec\u8fd8\u9700\u8981\u4e00\u4e2a\u9ed8\u8ba4\u76ee\u6807\u94fe\u3002\u8fd9\u662f\u4e00\u4e2a\u5f53\u8def\u7531\u5668\u65e0\u6cd5\u51b3\u5b9a\u4f7f\u7528\u54ea\u4e2a\u5b50\u94fe\u65f6\u8c03\u7528\u7684\u94fe\u3002\u5728\u4e0a\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u5f53\u8f93\u5165\u95ee\u9898\u4e0e\u7269\u7406\u3001\u6570\u5b66\u3001\u5386\u53f2\u6216\u8ba1\u7b97\u673a\u79d1\u5b66\u65e0\u5173\u65f6\uff0c\u53ef\u80fd\u4f1a\u8c03\u7528\u5b83\u3002"]}, {"cell_type": "code", "execution_count": 31, "id": "9f98018a", "metadata": {}, "outputs": [], "source": ["default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", "default_chain = LLMChain(llm=llm, prompt=default_prompt)"]}, {"cell_type": "markdown", "id": "948700c4", "metadata": {}, "source": ["#### 4.4.3 \u521b\u5efaLLM\u7528\u4e8e\u5728\u4e0d\u540c\u94fe\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u7684\u6a21\u677f\n", "\u8fd9\u5305\u62ec\u8981\u5b8c\u6210\u7684\u4efb\u52a1\u7684\u8bf4\u660e\u4ee5\u53ca\u8f93\u51fa\u5e94\u8be5\u91c7\u7528\u7684\u7279\u5b9a\u683c\u5f0f\u3002"]}, {"cell_type": "markdown", "id": "24f30c2c", "metadata": {}, "source": ["\u6ce8\u610f\uff1a\u6b64\u5904\u5728\u539f\u6559\u7a0b\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u4e00\u4e2a\u793a\u4f8b\uff0c\u4e3b\u8981\u662f\u56e0\u4e3a\"gpt-3.5-turbo\"\u6a21\u578b\u4e0d\u80fd\u5f88\u597d\u9002\u5e94\u7406\u89e3\u6a21\u677f\u7684\u610f\u601d\uff0c\u4f7f\u7528 \"text-davinci-003\" \u6216\u8005\"gpt-4-0613\"\u53ef\u4ee5\u5f88\u597d\u7684\u5de5\u4f5c\uff0c\u56e0\u6b64\u5728\u8fd9\u91cc\u591a\u52a0\u4e86\u793a\u4f8b\u63d0\u793a\u8ba9\u5176\u66f4\u597d\u7684\u5b66\u4e60\u3002\n", "eg:\n", "<< INPUT >>\n", "\"What is black body radiation?\"\n", "<< OUTPUT >>\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```"]}, {"cell_type": "code", "execution_count": 32, "id": "11b2e2ba", "metadata": {}, "outputs": [], "source": ["MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"Given a raw text input to a \\\n", "language model select the model prompt best suited for the input. \\\n", "You will be given the names of the available prompts and a \\\n", "description of what the prompt is best suited for. \\\n", "You may also revise the original input if you think that revising\\\n", "it will ultimately lead to a better response from the language model.\n", "\n", "<< FORMATTING >>\n", "Return a markdown code snippet with a JSON object formatted to look like:\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```\n", "\n", "REMEMBER: \"destination\" MUST be one of the candidate prompt \\\n", "names specified below OR it can be \"DEFAULT\" if the input is not\\\n", "well suited for any of the candidate prompts.\n", "REMEMBER: \"next_inputs\" can just be the original input \\\n", "if you don't think any modifications are needed.\n", "\n", "<< CANDIDATE PROMPTS >>\n", "{destinations}\n", "\n", "<< INPUT >>\n", "{{input}}\n", "\n", "<< OUTPUT (remember to include the ```json)>>\n", "\n", "eg:\n", "<< INPUT >>\n", "\"What is black body radiation?\"\n", "<< OUTPUT >>\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```\n", "\n", "\"\"\""]}, {"cell_type": "code", "execution_count": null, "id": "a7aae035", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "\n", "# \u591a\u63d0\u793a\u8def\u7531\u6a21\u677f\n", "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"\u7ed9\u8bed\u8a00\u6a21\u578b\u4e00\u4e2a\u539f\u59cb\u6587\u672c\u8f93\u5165\uff0c\\\n", "\u8ba9\u5176\u9009\u62e9\u6700\u9002\u5408\u8f93\u5165\u7684\u6a21\u578b\u63d0\u793a\u3002\\\n", "\u7cfb\u7edf\u5c06\u4e3a\u60a8\u63d0\u4f9b\u53ef\u7528\u63d0\u793a\u7684\u540d\u79f0\u4ee5\u53ca\u6700\u9002\u5408\u6539\u63d0\u793a\u7684\u63cf\u8ff0\u3002\\\n", "\u5982\u679c\u4f60\u8ba4\u4e3a\u4fee\u6539\u539f\u59cb\u8f93\u5165\u6700\u7ec8\u4f1a\u5bfc\u81f4\u8bed\u8a00\u6a21\u578b\u505a\u51fa\u66f4\u597d\u7684\u54cd\u5e94\uff0c\\\n", "\u4f60\u4e5f\u53ef\u4ee5\u4fee\u6539\u539f\u59cb\u8f93\u5165\u3002\n", "\n", "\n", "<< \u683c\u5f0f >>\n", "\u8fd4\u56de\u4e00\u4e2a\u5e26\u6709JSON\u5bf9\u8c61\u7684markdown\u4ee3\u7801\u7247\u6bb5\uff0c\u8be5JSON\u5bf9\u8c61\u7684\u683c\u5f0f\u5982\u4e0b\uff1a\n", "```json\n", "{{{{\n", " \"destination\": \u5b57\u7b26\u4e32 \\ \u4f7f\u7528\u7684\u63d0\u793a\u540d\u5b57\u6216\u8005\u4f7f\u7528 \"DEFAULT\"\n", " \"next_inputs\": \u5b57\u7b26\u4e32 \\ \u539f\u59cb\u8f93\u5165\u7684\u6539\u8fdb\u7248\u672c\n", "}}}}\n", "```\n", "\n", "\n", "\u8bb0\u4f4f\uff1a\u201cdestination\u201d\u5fc5\u987b\u662f\u4e0b\u9762\u6307\u5b9a\u7684\u5019\u9009\u63d0\u793a\u540d\u79f0\u4e4b\u4e00\uff0c\\\n", "\u6216\u8005\u5982\u679c\u8f93\u5165\u4e0d\u592a\u9002\u5408\u4efb\u4f55\u5019\u9009\u63d0\u793a\uff0c\\\n", "\u5219\u53ef\u4ee5\u662f \u201cDEFAULT\u201d \u3002\n", "\u8bb0\u4f4f\uff1a\u5982\u679c\u60a8\u8ba4\u4e3a\u4e0d\u9700\u8981\u4efb\u4f55\u4fee\u6539\uff0c\\\n", "\u5219 \u201cnext_inputs\u201d \u53ef\u4ee5\u53ea\u662f\u539f\u59cb\u8f93\u5165\u3002\n", "\n", "<< \u5019\u9009\u63d0\u793a >>\n", "{destinations}\n", "\n", "<< \u8f93\u5165 >>\n", "{{input}}\n", "\n", "<< \u8f93\u51fa (\u8bb0\u5f97\u8981\u5305\u542b ```json)>>\n", "\n", "\u6837\u4f8b:\n", "<< \u8f93\u5165 >>\n", "\"\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04?\"\n", "<< \u8f93\u51fa >>\n", "```json\n", "{{{{\n", " \"destination\": \u5b57\u7b26\u4e32 \\ \u4f7f\u7528\u7684\u63d0\u793a\u540d\u5b57\u6216\u8005\u4f7f\u7528 \"DEFAULT\"\n", " \"next_inputs\": \u5b57\u7b26\u4e32 \\ \u539f\u59cb\u8f93\u5165\u7684\u6539\u8fdb\u7248\u672c\n", "}}}}\n", "```\n", "\n", "\"\"\""]}, {"cell_type": "markdown", "id": "de5c46d0", "metadata": {}, "source": ["#### 4.4.4 \u6784\u5efa\u8def\u7531\u94fe\n", "\u9996\u5148\uff0c\u6211\u4eec\u901a\u8fc7\u683c\u5f0f\u5316\u4e0a\u9762\u5b9a\u4e49\u7684\u76ee\u6807\u521b\u5efa\u5b8c\u6574\u7684\u8def\u7531\u5668\u6a21\u677f\u3002\u8fd9\u4e2a\u6a21\u677f\u53ef\u4ee5\u9002\u7528\u8bb8\u591a\u4e0d\u540c\u7c7b\u578b\u7684\u76ee\u6807\u3002\n", "\u56e0\u6b64\uff0c\u5728\u8fd9\u91cc\uff0c\u60a8\u53ef\u4ee5\u6dfb\u52a0\u4e00\u4e2a\u4e0d\u540c\u7684\u5b66\u79d1\uff0c\u5982\u82f1\u8bed\u6216\u62c9\u4e01\u8bed\uff0c\u800c\u4e0d\u4ec5\u4ec5\u662f\u7269\u7406\u3001\u6570\u5b66\u3001\u5386\u53f2\u548c\u8ba1\u7b97\u673a\u79d1\u5b66\u3002\n", "\n", "\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u4ece\u8fd9\u4e2a\u6a21\u677f\u521b\u5efa\u63d0\u793a\u6a21\u677f\n", "\n", "\u6700\u540e\uff0c\u901a\u8fc7\u4f20\u5165llm\u548c\u6574\u4e2a\u8def\u7531\u63d0\u793a\u6765\u521b\u5efa\u8def\u7531\u94fe\u3002\u9700\u8981\u6ce8\u610f\u7684\u662f\u8fd9\u91cc\u6709\u8def\u7531\u8f93\u51fa\u89e3\u6790\uff0c\u8fd9\u5f88\u91cd\u8981\uff0c\u56e0\u4e3a\u5b83\u5c06\u5e2e\u52a9\u8fd9\u4e2a\u94fe\u8def\u51b3\u5b9a\u5728\u54ea\u4e9b\u5b50\u94fe\u8def\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002"]}, {"cell_type": "code", "execution_count": 34, "id": "1387109d", "metadata": {}, "outputs": [], "source": ["router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(\n", " destinations=destinations_str\n", ")\n", "router_prompt = PromptTemplate(\n", " template=router_template,\n", " input_variables=[\"input\"],\n", " output_parser=RouterOutputParser(),\n", ")\n", "\n", "router_chain = LLMRouterChain.from_llm(llm, router_prompt)"]}, {"cell_type": "markdown", "id": "7e92355c", "metadata": {}, "source": ["#### 4.4.5 \u521b\u5efa\u6574\u4f53\u94fe\u8def"]}, {"cell_type": "code", "execution_count": 35, "id": "2fb7d560", "metadata": {}, "outputs": [], "source": ["#\u591a\u63d0\u793a\u94fe\n", "chain = MultiPromptChain(router_chain=router_chain, #l\u8def\u7531\u94fe\u8def\n", " destination_chains=destination_chains, #\u76ee\u6807\u94fe\u8def\n", " default_chain=default_chain, #\u9ed8\u8ba4\u94fe\u8def\n", " verbose=True \n", " )"]}, {"cell_type": "markdown", "id": "086503f7", "metadata": {}, "source": ["#### 4.4.6 \u8fdb\u884c\u63d0\u95ee"]}, {"cell_type": "markdown", "id": "969cd878", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u95ee\u4e00\u4e2a\u7269\u7406\u95ee\u9898\uff0c\u6211\u4eec\u5e0c\u671b\u770b\u5230\u4ed6\u88ab\u8def\u7531\u5230\u7269\u7406\u94fe\u8def"]}, {"cell_type": "code", "execution_count": null, "id": "2217d987", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "physics: {'input': 'What is black body radiation?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Black body radiation is the electromagnetic radiation emitted by a perfect black body, which absorbs all incident radiation and reflects none. It is characterized by a continuous spectrum of radiated energy that is dependent on the temperature of the body, with higher temperatures leading to more intense and shorter wavelength radiation. This phenomenon is an important concept in thermal physics and has numerous applications, ranging from understanding stellar spectra to designing artificial light sources.'"]}, "metadata": {}, "output_type": "display_data"}], "source": ["# \u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f\n", "chain.run(\"What is black body radiation?\")"]}, {"cell_type": "code", "execution_count": 36, "id": "4446724c", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "physics: {'input': '\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u9ed1\u4f53\u8f90\u5c04\u662f\u6307\u4e00\u4e2a\u7406\u60f3\u5316\u7684\u7269\u4f53\uff0c\u5b83\u80fd\u591f\u5b8c\u5168\u5438\u6536\u6240\u6709\u5165\u5c04\u5230\u5b83\u8868\u9762\u7684\u8f90\u5c04\u80fd\u91cf\uff0c\u5e76\u4ee5\u70ed\u8f90\u5c04\u7684\u5f62\u5f0f\u91cd\u65b0\u53d1\u5c04\u51fa\u6765\u3002\u9ed1\u4f53\u8f90\u5c04\u7684\u7279\u70b9\u662f\u5176\u8f90\u5c04\u80fd\u91cf\u7684\u5206\u5e03\u4e0e\u6e29\u5ea6\u6709\u5173\uff0c\u968f\u7740\u6e29\u5ea6\u7684\u5347\u9ad8\uff0c\u8f90\u5c04\u80fd\u91cf\u7684\u5cf0\u503c\u4f1a\u5411\u66f4\u77ed\u7684\u6ce2\u957f\u65b9\u5411\u79fb\u52a8\u3002\u8fd9\u4e2a\u73b0\u8c61\u88ab\u79f0\u4e3a\u9ed1\u4f53\u8f90\u5c04\u8c31\u7684\u4f4d\u79fb\u5b9a\u5f8b\uff0c\u7531\u666e\u6717\u514b\u572820\u4e16\u7eaa\u521d\u63d0\u51fa\u3002\u9ed1\u4f53\u8f90\u5c04\u5728\u7814\u7a76\u70ed\u529b\u5b66\u3001\u91cf\u5b50\u529b\u5b66\u548c\u5b87\u5b99\u5b66\u7b49\u9886\u57df\u4e2d\u5177\u6709\u91cd\u8981\u7684\u5e94\u7528\u3002'"]}, "execution_count": 36, "metadata": {}, "output_type": "execute_result"}], "source": ["#\u4e2d\u6587\n", "chain.run(\"\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f\")"]}, {"cell_type": "code", "execution_count": 41, "id": "ef81eda3", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "History: {'input': '\u4f60\u77e5\u9053\u674e\u767d\u662f\u8c01\u561b?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u674e\u767d\u662f\u5510\u671d\u65f6\u671f\u7684\u4e00\u4f4d\u8457\u540d\u8bd7\u4eba\u3002\u4ed6\u7684\u8bd7\u6b4c\u4ee5\u8c6a\u653e\u3001\u5954\u653e\u3001\u81ea\u7531\u7684\u98ce\u683c\u8457\u79f0\uff0c\u88ab\u8a89\u4e3a\u201c\u8bd7\u4ed9\u201d\u3002\u4ed6\u7684\u4f5c\u54c1\u6d89\u53ca\u5e7f\u6cdb\uff0c\u5305\u62ec\u5c71\u6c34\u7530\u56ed\u3001\u5386\u53f2\u4f20\u8bf4\u3001\u54f2\u7406\u601d\u8003\u7b49\u591a\u4e2a\u65b9\u9762\uff0c\u5bf9\u4e2d\u56fd\u53e4\u5178\u6587\u5b66\u7684\u53d1\u5c55\u4ea7\u751f\u4e86\u6df1\u8fdc\u7684\u5f71\u54cd\u3002'"]}, "execution_count": 41, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"\u4f60\u77e5\u9053\u674e\u767d\u662f\u8c01\u561b?\")"]}, {"cell_type": "markdown", "id": "289c5ca9", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u95ee\u4e00\u4e2a\u6570\u5b66\u95ee\u9898\uff0c\u6211\u4eec\u5e0c\u671b\u770b\u5230\u4ed6\u88ab\u8def\u7531\u5230\u6570\u5b66\u94fe\u8def"]}, {"cell_type": "code", "execution_count": 22, "id": "3b717379", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "math: {'input': 'what is 2 + 2'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'As an AI language model, I can answer this question. The answer to 2 + 2 is 4.'"]}, "execution_count": 22, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u95ee\u9898\uff1a2+2\u7b49\u4e8e\u591a\u5c11\uff1f\n", "chain.run(\"what is 2 + 2\")"]}, {"cell_type": "code", "execution_count": 37, "id": "795bea17", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "math: {'input': '2 + 2 \u7b49\u4e8e\u591a\u5c11'}"]}, {"name": "stderr", "output_type": "stream", "text": ["Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised ServiceUnavailableError: The server is overloaded or not ready yet..\n"]}, {"name": "stdout", "output_type": "stream", "text": ["\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'2 + 2 \u7b49\u4e8e 4\u3002'"]}, "execution_count": 37, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"2 + 2 \u7b49\u4e8e\u591a\u5c11\")"]}, {"cell_type": "markdown", "id": "4186a2b9", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u4f20\u9012\u4e00\u4e2a\u4e0e\u4efb\u4f55\u5b50\u94fe\u8def\u90fd\u65e0\u5173\u7684\u95ee\u9898\u65f6\uff0c\u4f1a\u53d1\u751f\u4ec0\u4e48\u5462\uff1f\n", "\n", "\u8fd9\u91cc\uff0c\u6211\u4eec\u95ee\u4e86\u4e00\u4e2a\u5173\u4e8e\u751f\u7269\u5b66\u7684\u95ee\u9898\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u5b83\u9009\u62e9\u7684\u94fe\u8def\u662f\u65e0\u3002\u8fd9\u610f\u5473\u7740\u5b83\u5c06\u88ab**\u4f20\u9012\u5230\u9ed8\u8ba4\u94fe\u8def\uff0c\u5b83\u672c\u8eab\u53ea\u662f\u5bf9\u8bed\u8a00\u6a21\u578b\u7684\u901a\u7528\u8c03\u7528**\u3002\u8bed\u8a00\u6a21\u578b\u5e78\u8fd0\u5730\u5bf9\u751f\u7269\u5b66\u77e5\u9053\u5f88\u591a\uff0c\u6240\u4ee5\u5b83\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u3002"]}, {"cell_type": "code", "execution_count": 40, "id": "29e5be01", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "None: {'input': 'Why does every cell in our body contain DNA?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Every cell in our body contains DNA because DNA carries the genetic information that determines the characteristics and functions of each cell. DNA contains the instructions for the synthesis of proteins, which are essential for the structure and function of cells. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next. Therefore, every cell in our body needs DNA to carry out its specific functions and to maintain the integrity of the organism as a whole.'"]}, "execution_count": 40, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u95ee\u9898\uff1a\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f\n", "chain.run(\"Why does every cell in our body contain DNA?\")"]}, {"cell_type": "code", "execution_count": 38, "id": "a64d0759", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "None: {'input': '\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff0c\u662f\u56e0\u4e3aDNA\u662f\u9057\u4f20\u4fe1\u606f\u7684\u8f7d\u4f53\u3002DNA\u662f\u7531\u56db\u79cd\u78b1\u57fa\uff08\u817a\u560c\u5464\u3001\u9e1f\u560c\u5464\u3001\u80f8\u817a\u5627\u5576\u548c\u9cde\u560c\u5464\uff09\u7ec4\u6210\u7684\u957f\u94fe\u72b6\u5206\u5b50\uff0c\u5b83\u5b58\u50a8\u4e86\u751f\u7269\u4f53\u7684\u9057\u4f20\u4fe1\u606f\uff0c\u5305\u62ec\u4e2a\u4f53\u7684\u7279\u5f81\u3001\u751f\u957f\u53d1\u80b2\u3001\u4ee3\u8c22\u529f\u80fd\u7b49\u3002\u6bcf\u4e2a\u7ec6\u80de\u90fd\u9700\u8981\u8fd9\u4e9b\u9057\u4f20\u4fe1\u606f\u6765\u6267\u884c\u5176\u7279\u5b9a\u7684\u529f\u80fd\u548c\u4efb\u52a1\uff0c\u56e0\u6b64\u6bcf\u4e2a\u7ec6\u80de\u90fd\u9700\u8981\u5305\u542bDNA\u3002\u6b64\u5916\uff0cDNA\u8fd8\u80fd\u901a\u8fc7\u590d\u5236\u548c\u4f20\u9012\u7ed9\u4e0b\u4e00\u4ee3\u7ec6\u80de\u548c\u4e2a\u4f53\uff0c\u4ee5\u4fdd\u8bc1\u9057\u4f20\u4fe1\u606f\u7684\u4f20\u627f\u3002'"]}, "execution_count": 38, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f\")"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12"}}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{ + "cells": [ + { + "cell_type": "markdown", + "id": "52824b89-532a-4e54-87e9-1410813cd39e", + "metadata": {}, + "source": [ + "# 第四章 模型链\n", + "\n", + " - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n", + " - [二、LLMChain](#二、LLMChain)\n", + " - [三、Sequential Chains](#三、Sequential-Chains)\n", + " - [3.1 SimpleSequentialChain](#3.1-SimpleSequentialChain)\n", + " - [3.2 SequentialChain](#3.2-SequentialChain)\n", + " - [四、 Router Chain(路由链)](#四、-Router-Chain(路由链))\n", + " - [4.1 定义提示模板](#4.1-定义提示模板)\n", + " - [4.2 导入相关的包](#4.2-导入相关的包)\n", + " - [4.3 定义语言模型](#4.3-定义语言模型)\n", + " - [4.4 LLMRouterChain(此链使用 LLM 来确定如何路由事物)](#4.4-LLMRouterChain(此链使用-LLM-来确定如何路由事物))\n" + ] + }, + { + "cell_type": "markdown", + "id": "54810ef7", + "metadata": {}, + "source": [ + "链(Chains)通常将大语言模型(LLM)与提示(Prompt)结合在一起,基于此,我们可以对文本或数据进行一系列操作。\n", + "\n", + "链(Chains)可以一次性接受多个输入\n", + "\n", + "例如,我们可以创建一个链,该链接受用户输入,使用提示模板对其进行格式化,然后将格式化的响应传递给LLM。我们可以通过将多个链组合在一起,或者通过将链与其他组件组合在一起来构建更复杂的链。" + ] + }, + { + "cell_type": "markdown", + "id": "21009bf6-49bd-466e-8177-74c23533d938", + "metadata": { + "tags": [] + }, + "source": [ + "## 一、设置OpenAI API Key" + ] + }, + { + "cell_type": "markdown", + "id": "a2f5993b-f28d-4be4-984f-2d05be9f4579", + "metadata": {}, + "source": [ + "登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n", + "\n", + "- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n", + "- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n", + "\n", + "

\n", + " OPENAI_API_KEY=\"your_api_key\" \n", + "

\n", + " \n", + " 替换\"your_api_key\"为你自己的 API Key" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "adc3519c-4d12-4011-9223-2f3cb3c42b93", + "metadata": {}, + "outputs": [], + "source": [ + "# 下载需要的包python-dotenv和openai\n", + "# 如果你需要查看安装过程日志,可删除 -q \n", + "!pip install -q python-dotenv\n", + "!pip install -q openai" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1ad53241-bef6-42b8-894b-bcbbc8c64df7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import os\n", + "import openai\n", + "from dotenv import load_dotenv, find_dotenv\n", + "\n", + "# 读取本地/项目的环境变量。\n", + "\n", + "# find_dotenv()寻找并定位.env文件的路径\n", + "# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中 \n", + "# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n", + "_ = load_dotenv(find_dotenv())\n", + "\n", + "# 获取环境变量 OPENAI_API_KEY\n", + "openai.api_key = os.environ['OPENAI_API_KEY'] " + ] + }, + { + "cell_type": "markdown", + "id": "b940ce7c", + "metadata": { + "tags": [] + }, + "source": [ + "## 二、大语言模型链" + ] + }, + { + "cell_type": "markdown", + "id": "e000bd16", + "metadata": {}, + "source": [ + "大语言模型链(LLMChain)是一个简单但非常强大的链,也是后面我们将要介绍的许多链的基础。" + ] + }, + { + "cell_type": "markdown", + "id": "d57e93b9-52ba-4f86-a953-e4661b895a3d", + "metadata": {}, + "source": [ + "### 2.1 导入数据" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b84e441b", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install -q pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "df = pd.read_csv('data/Data.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b7a09c35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ProductReview
0Queen Size Sheet SetI ordered a king size set. My only criticism w...
1Waterproof Phone PouchI loved the waterproof sac, although the openi...
2Luxury Air MattressThis mattress had a small hole in the top of i...
3Pillows InsertThis is the best throw pillow fillers on Amazo...
4Milk Frother Handheld\\nI loved this product. But they only seem to l...
\n", + "
" + ], + "text/plain": [ + " Product Review\n", + "0 Queen Size Sheet Set I ordered a king size set. My only criticism w...\n", + "1 Waterproof Phone Pouch I loved the waterproof sac, although the openi...\n", + "2 Luxury Air Mattress This mattress had a small hole in the top of i...\n", + "3 Pillows Insert This is the best throw pillow fillers on Amazo...\n", + "4 Milk Frother Handheld\\n  I loved this product. But they only seem to l..." + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "markdown", + "id": "daa83d10-04ee-4355-abe3-ab699c9eaca9", + "metadata": {}, + "source": [ + "### 2.2 初始化语言模型" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e92dff22", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import ChatOpenAI \n", + "from langchain.prompts import ChatPromptTemplate \n", + "from langchain.chains import LLMChain " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "943237a7", + "metadata": {}, + "outputs": [], + "source": [ + "# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。\n", + "# 如果你想要每次得到不一样的有新意的答案,可以尝试调整该参数。\n", + "llm = ChatOpenAI(temperature=0.0) " + ] + }, + { + "cell_type": "markdown", + "id": "81887434", + "metadata": {}, + "source": [ + "### 2.3 初始化提示模版\n", + "初始化提示,这个提示将接受一个名为product的变量。该prompt将要求LLM生成一个描述制造该产品的公司的最佳名称" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "cdcdb42d", + "metadata": {}, + "outputs": [], + "source": [ + "prompt = ChatPromptTemplate.from_template( \n", + " \"What is the best name to describe \\\n", + " a company that makes {product}?\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "5c22cb13", + "metadata": {}, + "source": [ + "### 2.4 构建大语言模型链\n", + "\n", + "将大语言模型(LLM)和提示(Prompt)组合成链。这个大语言模型链非常简单,可以让我们以一种顺序的方式去通过运行提示并且结合到大语言模型中。" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d7abc20b", + "metadata": {}, + "outputs": [], + "source": [ + "chain = LLMChain(llm=llm, prompt=prompt)" + ] + }, + { + "cell_type": "markdown", + "id": "8d7d5ff6", + "metadata": {}, + "source": [ + "### 2.5 运行大语言模型链\n", + "因此,如果我们有一个名为\"Queen Size Sheet Set\"的产品,我们可以通过使用chain.run将其通过这个链运行" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ad44d1fb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Royal Linens.'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "product = \"Queen Size Sheet Set\"\n", + "chain.run(product)" + ] + }, + { + "cell_type": "markdown", + "id": "1e1ede1c", + "metadata": {}, + "source": [ + "您可以输入任何产品描述,然后查看链将输出什么结果" + ] + }, + { + "cell_type": "markdown", + "id": "8ab31583-5cdf-4885-94d7-59c0d3b90b2e", + "metadata": {}, + "source": [ + "### 2.6 中文提示" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "2181be10", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\"豪华床纺\"'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prompt = ChatPromptTemplate.from_template( \n", + " \"描述制造{product}的一个公司的最佳名称是什么?\"\n", + ")\n", + "chain = LLMChain(llm=llm, prompt=prompt)\n", + "product = \"大号床单套装\"\n", + "chain.run(product)" + ] + }, + { + "cell_type": "markdown", + "id": "49158430", + "metadata": {}, + "source": [ + "## 三、顺序链" + ] + }, + { + "cell_type": "markdown", + "id": "69b03469", + "metadata": {}, + "source": [ + "### 3.1 简单顺序链\n", + "\n", + "顺序链(SequentialChains)是按预定义顺序执行其链接的链。具体来说,我们将使用简单顺序链(SimpleSequentialChain),这是顺序链的最简单类型,其中每个步骤都有一个输入/输出,一个步骤的输出是下一个步骤的输入。" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "febee243", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chains import SimpleSequentialChain" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "5d019d6f", + "metadata": {}, + "outputs": [], + "source": [ + "llm = ChatOpenAI(temperature=0.9)" + ] + }, + { + "cell_type": "markdown", + "id": "0e732589", + "metadata": {}, + "source": [ + "#### 3.1.1 创建两个子链" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "2f31aa8a", + "metadata": {}, + "outputs": [], + "source": [ + "# 提示模板 1 :这个提示将接受产品并返回最佳名称来描述该公司\n", + "first_prompt = ChatPromptTemplate.from_template(\n", + " \"What is the best name to describe \\\n", + " a company that makes {product}?\"\n", + ")\n", + "\n", + "# Chain 1\n", + "chain_one = LLMChain(llm=llm, prompt=first_prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "3f5d5b76", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "# 提示模板 2 :接受公司名称,然后输出该公司的长为20个单词的描述\n", + "second_prompt = ChatPromptTemplate.from_template(\n", + " \"Write a 20 words description for the following \\\n", + " company:{company_name}\"\n", + ")\n", + "# chain 2\n", + "chain_two = LLMChain(llm=llm, prompt=second_prompt)" + ] + }, + { + "cell_type": "markdown", + "id": "3a1991f4", + "metadata": {}, + "source": [ + "#### 3.1.2 构建简单顺序链\n", + "现在我们可以组合两个LLMChain,以便我们可以在一个步骤中创建公司名称和描述" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6c1eb2c4", + "metadata": {}, + "outputs": [], + "source": [ + "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two], verbose=True)" + ] + }, + { + "cell_type": "markdown", + "id": "5122f26a", + "metadata": {}, + "source": [ + "给一个输入,然后运行上面的链" + ] + }, + { + "cell_type": "markdown", + "id": "9a80d102-da6b-49f4-8abd-7bff97211232", + "metadata": {}, + "source": [ + "#### 3.1.3 运行简单顺序链" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "78458efe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "\u001b[36;1m\u001b[1;3mRoyal Rest Linens\u001b[0m\n", + "\u001b[33;1m\u001b[1;3mRoyal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "\"Royal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\"" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "product = \"Queen Size Sheet Set\"\n", + "overall_simple_chain.run(product)" + ] + }, + { + "cell_type": "markdown", + "id": "3983eb68-adf0-4c18-beed-ff6fc09cd78b", + "metadata": {}, + "source": [ + "#### 3.1.4 中文提示" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "c7c32997", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", + "\u001b[36;1m\u001b[1;3m\"尺寸王床品有限公司\"\u001b[0m\n", + "\u001b[33;1m\u001b[1;3m尺寸王床品有限公司是一家专注于床上用品生产的公司。\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'尺寸王床品有限公司是一家专注于床上用品生产的公司。'" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 中文\n", + "\n", + "first_prompt = ChatPromptTemplate.from_template( \n", + " \"描述制造{product}的一个公司的最好的名称是什么\"\n", + ")\n", + "chain_one = LLMChain(llm=llm, prompt=first_prompt)\n", + "\n", + "second_prompt = ChatPromptTemplate.from_template( \n", + " \"写一个20字的描述对于下面这个\\\n", + " 公司:{company_name}的\"\n", + ")\n", + "chain_two = LLMChain(llm=llm, prompt=second_prompt)\n", + "\n", + "\n", + "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],verbose=True)\n", + "product = \"大号床单套装\"\n", + "overall_simple_chain.run(product)" + ] + }, + { + "cell_type": "markdown", + "id": "7b5ce18c", + "metadata": {}, + "source": [ + "### 3.2 顺序链" + ] + }, + { + "cell_type": "markdown", + "id": "1e69f4c0", + "metadata": {}, + "source": [ + "当只有一个输入和一个输出时,简单顺序链(SimpleSequentialChain)即可实现。当有多个输入或多个输出时,我们则需要使用顺序链(SequentialChain)来实现。" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "4c129ef6", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chains import SequentialChain\n", + "from langchain.chat_models import ChatOpenAI #导入OpenAI模型\n", + "from langchain.prompts import ChatPromptTemplate #导入聊天提示模板\n", + "from langchain.chains import LLMChain #导入LLM链。" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "03a8e203", + "metadata": {}, + "outputs": [], + "source": [ + "llm = ChatOpenAI(temperature=0.9)" + ] + }, + { + "cell_type": "markdown", + "id": "9811445c", + "metadata": {}, + "source": [ + "接下来我们将创建一系列的链,然后一个接一个使用他们" + ] + }, + { + "cell_type": "markdown", + "id": "df9e87ec-b99a-4130-a5b5-cdce064dc6ca", + "metadata": {}, + "source": [ + "#### 3.2.1 创建四个子链" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "016187ac", + "metadata": {}, + "outputs": [], + "source": [ + "#子链1\n", + "\n", + "# prompt模板 1: 翻译成英语(把下面的review翻译成英语)\n", + "first_prompt = ChatPromptTemplate.from_template(\n", + " \"Translate the following review to english:\"\n", + " \"\\n\\n{Review}\"\n", + ")\n", + "# chain 1: 输入:Review 输出: 英文的 Review\n", + "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "0fb0730e", + "metadata": {}, + "outputs": [], + "source": [ + "#子链2\n", + "\n", + "# prompt模板 2: 用一句话总结下面的 review\n", + "second_prompt = ChatPromptTemplate.from_template(\n", + " \"Can you summarize the following review in 1 sentence:\"\n", + " \"\\n\\n{English_Review}\"\n", + ")\n", + "# chain 2: 输入:英文的Review 输出:总结\n", + "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "6accf92d", + "metadata": {}, + "outputs": [], + "source": [ + "#子链3\n", + "\n", + "# prompt模板 3: 下面review使用的什么语言\n", + "third_prompt = ChatPromptTemplate.from_template(\n", + " \"What language is the following review:\\n\\n{Review}\"\n", + ")\n", + "# chain 3: 输入:Review 输出:语言\n", + "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "c7a46121", + "metadata": {}, + "outputs": [], + "source": [ + "#子链4\n", + "\n", + "# prompt模板 4: 使用特定的语言对下面的总结写一个后续回复\n", + "fourth_prompt = ChatPromptTemplate.from_template(\n", + " \"Write a follow up response to the following \"\n", + " \"summary in the specified language:\"\n", + " \"\\n\\nSummary: {summary}\\n\\nLanguage: {language}\"\n", + ")\n", + "# chain 4: 输入: 总结, 语言 输出: 后续回复\n", + "chain_four = LLMChain(llm=llm, prompt=fourth_prompt, output_key=\"followup_message\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "ff435291-5d20-4c3e-9ed7-76a1140f96d2", + "metadata": {}, + "source": [ + "#### 3.2.2 对四个子链进行组合" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "89603117", + "metadata": {}, + "outputs": [], + "source": [ + "#输入:review \n", + "#输出:英文review,总结,后续回复 \n", + "overall_chain = SequentialChain(\n", + " chains=[chain_one, chain_two, chain_three, chain_four],\n", + " input_variables=[\"Review\"],\n", + " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", + " verbose=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "0509de01", + "metadata": {}, + "source": [ + "让我们选择一篇评论并通过整个链传递它,可以发现,原始review是法语,可以把英文review看做是一种翻译,接下来是根据英文review得到的总结,最后输出的是用法语原文进行的续写信息。" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "51b04f45", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "{'Review': \"Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\\nVieux lot ou contrefaçon !?\",\n", + " 'English_Review': \"I find the taste mediocre. The foam doesn't hold, it's weird. I buy the same ones in the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", + " 'summary': 'The reviewer is disappointed with the taste and consistency of the product, suspecting that either an old batch or counterfeit version is the cause.',\n", + " 'followup_message': \"Réponse de suivi :\\n\\nCher(e) critique,\\n\\nNous sommes désolés d'apprendre que notre produit ne répond pas à vos attentes. Nous prenons très au sérieux les commentaires de nos clients et nous tenons à vous rassurer que nous attachons une grande importance à la qualité de nos produits.\\n\\nNous vérifions constamment nos processus de production afin de nous assurer que nos produits sont toujours frais et authentiques. Si vous pensez avoir reçu un produit contrefait ou un lot périmé, nous vous prions de nous contacter directement afin de résoudre ce problème au plus vite. Nous avons un service client dédié qui sera ravi de vous aider avec votre préoccupation.\\n\\nNous tenons à nous excuser pour toute déception ou désagrément que cela aurait pu causer. Votre satisfaction est notre priorité absolue et nous ferons tout notre possible pour remédier à la situation et regagner votre confiance.\\n\\nNous vous remercions de votre compréhension et de votre patience. Votre avis est important pour nous et nous espérons avoir l'occasion de nous rattraper à l'avenir.\\n\\nCordialement,\\nL'équipe de [Nom de l'entreprise]\"}" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "review = df.Review[5]\n", + "overall_chain(review)" + ] + }, + { + "cell_type": "markdown", + "id": "18d72f1d-8a1e-4eb6-b00f-1963b3cf3adb", + "metadata": {}, + "source": [ + "#### 3.2.3 中文提示" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "31624a7c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new chain...\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "{'Review': \"Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\\nVieux lot ou contrefaçon !?\",\n", + " 'English_Review': \"I find the taste mediocre. The foam doesn't last, it's weird. I buy the same ones from the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", + " 'summary': \"The taste is mediocre, the foam doesn't last, and there is suspicion of old batch or counterfeit.\",\n", + " 'followup_message': \"回复: Je suis désolé de vous entendre dire que le goût est moyen et que la mousse ne dure pas longtemps. Nous prenons ces problèmes très au sérieux. Nous allons enquêter pour vérifier s'il s'agit d'un ancien lot ou d'une contrefaçon. Votre satisfaction est notre priorité et nous ferons de notre mieux pour résoudre ce problème. Merci de nous avoir informés.\"}" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 中文\n", + "\n", + "#子链1\n", + "# prompt模板 1: 翻译成英语(把下面的review翻译成英语)\n", + "first_prompt = ChatPromptTemplate.from_template(\n", + " \"把下面的评论review翻译成英文:\"\n", + " \"\\n\\n{Review}\"\n", + ")\n", + "# chain 1: 输入:Review 输出:英文的 Review\n", + "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")\n", + "\n", + "#子链2\n", + "# prompt模板 2: 用一句话总结下面的 review\n", + "second_prompt = ChatPromptTemplate.from_template(\n", + " \"请你用一句话来总结下面的评论review:\"\n", + " \"\\n\\n{English_Review}\"\n", + ")\n", + "# chain 2: 输入:英文的Review 输出:总结\n", + "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n", + "\n", + "\n", + "#子链3\n", + "# prompt模板 3: 下面review使用的什么语言\n", + "third_prompt = ChatPromptTemplate.from_template(\n", + " \"下面的评论review使用的什么语言:\\n\\n{Review}\"\n", + ")\n", + "# chain 3: 输入:Review 输出:语言\n", + "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n", + "\n", + "\n", + "#子链4\n", + "# prompt模板 4: 使用特定的语言对下面的总结写一个后续回复\n", + "fourth_prompt = ChatPromptTemplate.from_template(\n", + " \"使用特定的语言对下面的总结写一个后续回复:\"\n", + " \"\\n\\n总结: {summary}\\n\\n语言: {language}\"\n", + ")\n", + "# chain 4: 输入: 总结, 语言 输出: 后续回复\n", + "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n", + " output_key=\"followup_message\"\n", + " )\n", + "\n", + "\n", + "# 对四个子链进行组合\n", + "#输入:review 输出:英文review,总结,后续回复 \n", + "overall_chain = SequentialChain(\n", + " chains=[chain_one, chain_two, chain_three, chain_four],\n", + " input_variables=[\"Review\"],\n", + " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", + " verbose=True\n", + ")\n", + "\n", + "\n", + "review = df.Review[5]\n", + "overall_chain(review)" + ] + }, + { + "cell_type": "markdown", + "id": "3041ea4c", + "metadata": {}, + "source": [ + "## 四、 路由链" + ] + }, + { + "cell_type": "markdown", + "id": "f0c32f97", + "metadata": {}, + "source": [ + "到目前为止,我们已经学习了大语言模型链和顺序链。但是,如果我们想做一些更复杂的事情怎么办?\n", + "\n", + "一个相当常见但基本的操作是根据输入将其路由到一条链,具体取决于该输入到底是什么。如果你有多个子链,每个子链都专门用于特定类型的输入,那么可以组成一个路由链,它首先决定将它传递给哪个子链,然后将它传递给那个链。\n", + "\n", + "路由器由两个组件组成:\n", + "\n", + "- 路由链(Router Chain):路由器链本身,负责选择要调用的下一个链\n", + "- destination_chains:路由器链可以路由到的链\n", + "\n", + "举一个具体的例子,让我们看一下我们在不同类型的链之间路由的地方,我们在这里有不同的prompt: " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "31b06fc8", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chains.router import MultiPromptChain #导入多提示链\n", + "from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser\n", + "from langchain.prompts import PromptTemplate" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "f3f50bcc", + "metadata": {}, + "outputs": [], + "source": [ + "llm = ChatOpenAI(temperature=0)" + ] + }, + { + "cell_type": "markdown", + "id": "cb1b4708", + "metadata": {}, + "source": [ + "### 4.1 定义提示模板" + ] + }, + { + "cell_type": "markdown", + "id": "c3b85285-c736-4a5d-bd14-d9b5025ca29b", + "metadata": {}, + "source": [ + "首先,我们定义提示适用于不同场景下的提示模板。" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "ade83f4f", + "metadata": {}, + "outputs": [], + "source": [ + "#第一个提示适合回答物理问题\n", + "physics_template = \"\"\"You are a very smart physics professor. \\\n", + "You are great at answering questions about physics in a concise\\\n", + "and easy to understand manner. \\\n", + "When you don't know the answer to a question you admit\\\n", + "that you don't know.\n", + "\n", + "Here is a question:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第二个提示适合回答数学问题\n", + "math_template = \"\"\"You are a very good mathematician. \\\n", + "You are great at answering math questions. \\\n", + "You are so good because you are able to break down \\\n", + "hard problems into their component parts, \n", + "answer the component parts, and then put them together\\\n", + "to answer the broader question.\n", + "\n", + "Here is a question:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第三个适合回答历史问题\n", + "history_template = \"\"\"You are a very good historian. \\\n", + "You have an excellent knowledge of and understanding of people,\\\n", + "events and contexts from a range of historical periods. \\\n", + "You have the ability to think, reflect, debate, discuss and \\\n", + "evaluate the past. You have a respect for historical evidence\\\n", + "and the ability to make use of it to support your explanations \\\n", + "and judgements.\n", + "\n", + "Here is a question:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第四个适合回答计算机问题\n", + "computerscience_template = \"\"\" You are a successful computer scientist.\\\n", + "You have a passion for creativity, collaboration,\\\n", + "forward-thinking, confidence, strong problem-solving capabilities,\\\n", + "understanding of theories and algorithms, and excellent communication \\\n", + "skills. You are great at answering coding questions. \\\n", + "You are so good because you know how to solve a problem by \\\n", + "describing the solution in imperative steps \\\n", + "that a machine can easily interpret and you know how to \\\n", + "choose a solution that has a good balance between \\\n", + "time complexity and space complexity. \n", + "\n", + "Here is a question:\n", + "{input}\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "cb3b749b-0d3c-46f2-afab-b1213f208b13", + "metadata": {}, + "source": [ + "### 4.2 对提示模版进行命名和描述" + ] + }, + { + "cell_type": "markdown", + "id": "6922b35e", + "metadata": {}, + "source": [ + "在定义了这些提示模板后,我们可以为每个模板命名,并给出具体描述。例如,第一个物理学的描述适合回答关于物理学的问题,这些信息将传递给路由链,然后由路由链决定何时使用此子链。" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "141a3d32", + "metadata": {}, + "outputs": [], + "source": [ + "prompt_infos = [\n", + " {\n", + " \"name\": \"physics\", \n", + " \"description\": \"Good for answering questions about physics\", \n", + " \"prompt_template\": physics_template\n", + " },\n", + " {\n", + " \"name\": \"math\", \n", + " \"description\": \"Good for answering math questions\", \n", + " \"prompt_template\": math_template\n", + " },\n", + " {\n", + " \"name\": \"History\", \n", + " \"description\": \"Good for answering history questions\", \n", + " \"prompt_template\": history_template\n", + " },\n", + " {\n", + " \"name\": \"computer science\", \n", + " \"description\": \"Good for answering computer science questions\", \n", + " \"prompt_template\": computerscience_template\n", + " }\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "8795cd42", + "metadata": {}, + "source": [ + "LLMRouterChain(此链使用 LLM 来确定如何路由事物)\n", + "\n", + "在这里,我们需要一个**多提示链**。这是一种特定类型的链,用于在多个不同的提示模板之间进行路由。 但是这只是路由的一种类型,我们也可以在任何类型的链之间进行路由。\n", + "\n", + "这里我们要实现的几个类是大模型路由器链。这个类本身使用语言模型来在不同的子链之间进行路由。这就是上面提供的描述和名称将被使用的地方。" + ] + }, + { + "cell_type": "markdown", + "id": "46633b43", + "metadata": {}, + "source": [ + "### 4.3 基于提示模版信息创建相应目标链 \n", + "目标链是由路由链调用的链,每个目标链都是一个语言模型链" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "8eefec24", + "metadata": {}, + "outputs": [], + "source": [ + "destination_chains = {}\n", + "for p_info in prompt_infos:\n", + " name = p_info[\"name\"]\n", + " prompt_template = p_info[\"prompt_template\"]\n", + " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", + " chain = LLMChain(llm=llm, prompt=prompt)\n", + " destination_chains[name] = chain \n", + " \n", + "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n", + "destinations_str = \"\\n\".join(destinations)" + ] + }, + { + "cell_type": "markdown", + "id": "eba115de", + "metadata": { + "tags": [] + }, + "source": [ + "### 4.4 创建默认目标链\n", + "除了目标链之外,我们还需要一个默认目标链。这是一个当路由器无法决定使用哪个子链时调用的链。在上面的示例中,当输入问题与物理、数学、历史或计算机科学无关时,可能会调用它。" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "9f98018a", + "metadata": {}, + "outputs": [], + "source": [ + "default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", + "default_chain = LLMChain(llm=llm, prompt=default_prompt)" + ] + }, + { + "cell_type": "markdown", + "id": "948700c4", + "metadata": {}, + "source": [ + "### 4.5 定义不同链之间的路由模板\n", + "\n", + "这包括要完成的任务的说明以及输出应该采用的特定格式。" + ] + }, + { + "cell_type": "markdown", + "id": "24f30c2c", + "metadata": {}, + "source": [ + "注意:此处在原教程的基础上添加了一个示例,主要是因为\"gpt-3.5-turbo\"模型不能很好适应理解模板的意思,使用 \"text-davinci-003\" 或者\"gpt-4-0613\"可以很好的工作,因此在这里多加了示例提示让其更好的学习。\n", + "eg:\n", + "<< INPUT >>\n", + "\"What is black body radiation?\"\n", + "<< OUTPUT >>\n", + "```json\n", + "{{{{\n", + " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", + " \"next_inputs\": string \\ a potentially modified version of the original input\n", + "}}}}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "11b2e2ba", + "metadata": {}, + "outputs": [], + "source": [ + "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"Given a raw text input to a \\\n", + "language model select the model prompt best suited for the input. \\\n", + "You will be given the names of the available prompts and a \\\n", + "description of what the prompt is best suited for. \\\n", + "You may also revise the original input if you think that revising\\\n", + "it will ultimately lead to a better response from the language model.\n", + "\n", + "<< FORMATTING >>\n", + "Return a markdown code snippet with a JSON object formatted to look like:\n", + "```json\n", + "{{{{\n", + " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", + " \"next_inputs\": string \\ a potentially modified version of the original input\n", + "}}}}\n", + "```\n", + "\n", + "REMEMBER: \"destination\" MUST be one of the candidate prompt \\\n", + "names specified below OR it can be \"DEFAULT\" if the input is not\\\n", + "well suited for any of the candidate prompts.\n", + "REMEMBER: \"next_inputs\" can just be the original input \\\n", + "if you don't think any modifications are needed.\n", + "\n", + "<< CANDIDATE PROMPTS >>\n", + "{destinations}\n", + "\n", + "<< INPUT >>\n", + "{{input}}\n", + "\n", + "<< OUTPUT (remember to include the ```json)>>\n", + "\n", + "eg:\n", + "<< INPUT >>\n", + "\"What is black body radiation?\"\n", + "<< OUTPUT >>\n", + "```json\n", + "{{{{\n", + " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", + " \"next_inputs\": string \\ a potentially modified version of the original input\n", + "}}}}\n", + "```\n", + "\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "de5c46d0", + "metadata": {}, + "source": [ + "### 4.6 构建路由链\n", + "首先,我们通过格式化上面定义的目标创建完整的路由器模板。这个模板可以适用许多不同类型的目标。\n", + "因此,在这里,您可以添加一个不同的学科,如英语或拉丁语,而不仅仅是物理、数学、历史和计算机科学。\n", + "\n", + "接下来,我们从这个模板创建提示模板\n", + "\n", + "最后,通过传入llm和整个路由提示来创建路由链。需要注意的是这里有路由输出解析,这很重要,因为它将帮助这个链路决定在哪些子链路之间进行路由。" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "1387109d", + "metadata": {}, + "outputs": [], + "source": [ + "router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(\n", + " destinations=destinations_str\n", + ")\n", + "router_prompt = PromptTemplate(\n", + " template=router_template,\n", + " input_variables=[\"input\"],\n", + " output_parser=RouterOutputParser(),\n", + ")\n", + "\n", + "router_chain = LLMRouterChain.from_llm(llm, router_prompt)" + ] + }, + { + "cell_type": "markdown", + "id": "7e92355c", + "metadata": {}, + "source": [ + "### 4.7 创建整体链路" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "2fb7d560", + "metadata": {}, + "outputs": [], + "source": [ + "#多提示链\n", + "chain = MultiPromptChain(router_chain=router_chain, #l路由链路\n", + " destination_chains=destination_chains, #目标链路\n", + " default_chain=default_chain, #默认链路\n", + " verbose=True \n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "086503f7", + "metadata": {}, + "source": [ + "### 4.8 进行提问" + ] + }, + { + "cell_type": "markdown", + "id": "969cd878", + "metadata": {}, + "source": [ + "如果我们问一个物理问题,我们希望看到他被路由到物理链路" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2217d987", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "physics: {'input': 'What is black body radiation?'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Black body radiation is the electromagnetic radiation emitted by a perfect black body, which absorbs all incident radiation and reflects none. It is characterized by a continuous spectrum of radiated energy that is dependent on the temperature of the body, with higher temperatures leading to more intense and shorter wavelength radiation. This phenomenon is an important concept in thermal physics and has numerous applications, ranging from understanding stellar spectra to designing artificial light sources.'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# 问题:什么是黑体辐射?\n", + "chain.run(\"What is black body radiation?\")" + ] + }, + { + "cell_type": "markdown", + "id": "289c5ca9", + "metadata": {}, + "source": [ + "如果我们问一个数学问题,我们希望看到他被路由到数学链路" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3b717379", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "math: {'input': 'what is 2 + 2'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'As an AI language model, I can answer this question. The answer to 2 + 2 is 4.'" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 问题:2+2等于多少?\n", + "chain.run(\"what is 2 + 2\")" + ] + }, + { + "cell_type": "markdown", + "id": "4186a2b9", + "metadata": {}, + "source": [ + "如果我们传递一个与任何子链路都无关的问题时,会发生什么呢?\n", + "\n", + "这里,我们问了一个关于生物学的问题,我们可以看到它选择的链路是无。这意味着它将被**传递到默认链路,它本身只是对语言模型的通用调用**。语言模型幸运地对生物学知道很多,所以它可以帮助我们。" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "29e5be01", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "None: {'input': 'Why does every cell in our body contain DNA?'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Every cell in our body contains DNA because DNA carries the genetic information that determines the characteristics and functions of each cell. DNA contains the instructions for the synthesis of proteins, which are essential for the structure and function of cells. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next. Therefore, every cell in our body needs DNA to carry out its specific functions and to maintain the integrity of the organism as a whole.'" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 问题:为什么我们身体里的每个细胞都包含DNA?\n", + "chain.run(\"Why does every cell in our body contain DNA?\")" + ] + }, + { + "cell_type": "markdown", + "id": "753b5f1d-b010-4f33-a928-d3b9e85bf289", + "metadata": {}, + "source": [ + "### 4.9 中文提示" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "f7fade7a", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "#第一个提示适合回答物理问题\n", + "physics_template = \"\"\"你是一个非常聪明的物理专家。 \\\n", + "你擅长用一种简洁并且易于理解的方式去回答问题。\\\n", + "当你不知道问题的答案时,你承认\\\n", + "你不知道.\n", + "\n", + "这是一个问题:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第二个提示适合回答数学问题\n", + "math_template = \"\"\"你是一个非常优秀的数学家。 \\\n", + "你擅长回答数学问题。 \\\n", + "你之所以如此优秀, \\\n", + "是因为你能够将棘手的问题分解为组成部分,\\\n", + "回答组成部分,然后将它们组合在一起,回答更广泛的问题。\n", + "\n", + "这是一个问题:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第三个适合回答历史问题\n", + "history_template = \"\"\"你是以为非常优秀的历史学家。 \\\n", + "你对一系列历史时期的人物、事件和背景有着极好的学识和理解\\\n", + "你有能力思考、反思、辩证、讨论和评估过去。\\\n", + "你尊重历史证据,并有能力利用它来支持你的解释和判断。\n", + "\n", + "这是一个问题:\n", + "{input}\"\"\"\n", + "\n", + "\n", + "#第四个适合回答计算机问题\n", + "computerscience_template = \"\"\" 你是一个成功的计算机科学专家。\\\n", + "你有创造力、协作精神、\\\n", + "前瞻性思维、自信、解决问题的能力、\\\n", + "对理论和算法的理解以及出色的沟通技巧。\\\n", + "你非常擅长回答编程问题。\\\n", + "你之所以如此优秀,是因为你知道 \\\n", + "如何通过以机器可以轻松解释的命令式步骤描述解决方案来解决问题,\\\n", + "并且你知道如何选择在时间复杂性和空间复杂性之间取得良好平衡的解决方案。\n", + "\n", + "这还是一个输入:\n", + "{input}\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "deb8aafc", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "prompt_infos = [\n", + " {\n", + " \"名字\": \"物理学\", \n", + " \"描述\": \"擅长回答关于物理学的问题\", \n", + " \"提示模板\": physics_template\n", + " },\n", + " {\n", + " \"名字\": \"数学\", \n", + " \"描述\": \"擅长回答数学问题\", \n", + " \"提示模板\": math_template\n", + " },\n", + " {\n", + " \"名字\": \"历史\", \n", + " \"描述\": \"擅长回答历史问题\", \n", + " \"提示模板\": history_template\n", + " },\n", + " {\n", + " \"名字\": \"计算机科学\", \n", + " \"描述\": \"擅长回答计算机科学问题\", \n", + " \"提示模板\": computerscience_template\n", + " }\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd6eb641", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "destination_chains = {}\n", + "for p_info in prompt_infos:\n", + " name = p_info[\"名字\"]\n", + " prompt_template = p_info[\"提示模板\"]\n", + " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", + " chain = LLMChain(llm=llm, prompt=prompt)\n", + " destination_chains[name] = chain \n", + " \n", + "destinations = [f\"{p['名字']}: {p['描述']}\" for p in prompt_infos]\n", + "destinations_str = \"\\n\".join(destinations)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af088d6b-a70b-4cd7-bc6e-4ad7b32e6ae1", + "metadata": {}, + "outputs": [], + "source": [ + "default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", + "default_chain = LLMChain(llm=llm, prompt=default_prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7aae035", + "metadata": {}, + "outputs": [], + "source": [ + "# 中文\n", + "\n", + "# 多提示路由模板\n", + "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"给语言模型一个原始文本输入,\\\n", + "让其选择最适合输入的模型提示。\\\n", + "系统将为您提供可用提示的名称以及最适合改提示的描述。\\\n", + "如果你认为修改原始输入最终会导致语言模型做出更好的响应,\\\n", + "你也可以修改原始输入。\n", + "\n", + "\n", + "<< 格式 >>\n", + "返回一个带有JSON对象的markdown代码片段,该JSON对象的格式如下:\n", + "```json\n", + "{{{{\n", + " \"destination\": 字符串 \\ 使用的提示名字或者使用 \"DEFAULT\"\n", + " \"next_inputs\": 字符串 \\ 原始输入的改进版本\n", + "}}}}\n", + "```\n", + "\n", + "\n", + "记住:“destination”必须是下面指定的候选提示名称之一,\\\n", + "或者如果输入不太适合任何候选提示,\\\n", + "则可以是 “DEFAULT” 。\n", + "记住:如果您认为不需要任何修改,\\\n", + "则 “next_inputs” 可以只是原始输入。\n", + "\n", + "<< 候选提示 >>\n", + "{destinations}\n", + "\n", + "<< 输入 >>\n", + "{{input}}\n", + "\n", + "<< 输出 (记得要包含 ```json)>>\n", + "\n", + "样例:\n", + "<< 输入 >>\n", + "\"什么是黑体辐射?\"\n", + "<< 输出 >>\n", + "```json\n", + "{{{{\n", + " \"destination\": 字符串 \\ 使用的提示名字或者使用 \"DEFAULT\"\n", + " \"next_inputs\": 字符串 \\ 原始输入的改进版本\n", + "}}}}\n", + "```\n", + "\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7470b25c-ef82-496c-a6e0-e04b99b08e70", + "metadata": {}, + "outputs": [], + "source": [ + "#多提示链\n", + "chain = MultiPromptChain(router_chain=router_chain, #l路由链路\n", + " destination_chains=destination_chains, #目标链路\n", + " default_chain=default_chain, #默认链路\n", + " verbose=True \n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "4446724c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "physics: {'input': '什么是黑体辐射?'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'黑体辐射是指一个理想化的物体,它能够完全吸收所有入射到它表面的辐射能量,并以热辐射的形式重新发射出来。黑体辐射的特点是其辐射能量的分布与温度有关,随着温度的升高,辐射能量的峰值会向更短的波长方向移动。这个现象被称为黑体辐射谱的位移定律,由普朗克在20世纪初提出。黑体辐射在研究热力学、量子力学和宇宙学等领域中具有重要的应用。'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#中文\n", + "chain.run(\"什么是黑体辐射?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "ef81eda3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "History: {'input': '你知道李白是谁嘛?'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'李白是唐朝时期的一位著名诗人。他的诗歌以豪放、奔放、自由的风格著称,被誉为“诗仙”。他的作品涉及广泛,包括山水田园、历史传说、哲理思考等多个方面,对中国古典文学的发展产生了深远的影响。'" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 中文\n", + "chain.run(\"你知道李白是谁嘛?\")" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "795bea17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "math: {'input': '2 + 2 等于多少'}" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised ServiceUnavailableError: The server is overloaded or not ready yet..\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'2 + 2 等于 4。'" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 中文\n", + "chain.run(\"2 + 2 等于多少\")" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "a64d0759", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", + "None: {'input': '为什么我们身体里的每个细胞都包含DNA?'}\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'我们身体里的每个细胞都包含DNA,是因为DNA是遗传信息的载体。DNA是由四种碱基(腺嘌呤、鸟嘌呤、胸腺嘧啶和鳞嘌呤)组成的长链状分子,它存储了生物体的遗传信息,包括个体的特征、生长发育、代谢功能等。每个细胞都需要这些遗传信息来执行其特定的功能和任务,因此每个细胞都需要包含DNA。此外,DNA还能通过复制和传递给下一代细胞和个体,以保证遗传信息的传承。'" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 中文\n", + "chain.run(\"为什么我们身体里的每个细胞都包含DNA?\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 41bacc4f36b968b8500ab4220b25b39332e0c8c9 Mon Sep 17 00:00:00 2001 From: joyenjoye Date: Sun, 16 Jul 2023 16:30:56 +0800 Subject: [PATCH 4/5] Update Chapter 4 --- .../4.模型链 Chains.ipynb | 1732 +---------------- 1 file changed, 1 insertion(+), 1731 deletions(-) diff --git a/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb b/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb index 85d6620..f4f60b1 100644 --- a/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb +++ b/content/LangChain for LLM Application Development/4.模型链 Chains.ipynb @@ -1,1731 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "52824b89-532a-4e54-87e9-1410813cd39e", - "metadata": {}, - "source": [ - "# 第四章 模型链\n", - "\n", - " - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n", - " - [二、LLMChain](#二、LLMChain)\n", - " - [三、Sequential Chains](#三、Sequential-Chains)\n", - " - [3.1 SimpleSequentialChain](#3.1-SimpleSequentialChain)\n", - " - [3.2 SequentialChain](#3.2-SequentialChain)\n", - " - [四、 Router Chain(路由链)](#四、-Router-Chain(路由链))\n", - " - [4.1 定义提示模板](#4.1-定义提示模板)\n", - " - [4.2 导入相关的包](#4.2-导入相关的包)\n", - " - [4.3 定义语言模型](#4.3-定义语言模型)\n", - " - [4.4 LLMRouterChain(此链使用 LLM 来确定如何路由事物)](#4.4-LLMRouterChain(此链使用-LLM-来确定如何路由事物))\n" - ] - }, - { - "cell_type": "markdown", - "id": "54810ef7", - "metadata": {}, - "source": [ - "链(Chains)通常将大语言模型(LLM)与提示(Prompt)结合在一起,基于此,我们可以对文本或数据进行一系列操作。\n", - "\n", - "链(Chains)可以一次性接受多个输入\n", - "\n", - "例如,我们可以创建一个链,该链接受用户输入,使用提示模板对其进行格式化,然后将格式化的响应传递给LLM。我们可以通过将多个链组合在一起,或者通过将链与其他组件组合在一起来构建更复杂的链。" - ] - }, - { - "cell_type": "markdown", - "id": "21009bf6-49bd-466e-8177-74c23533d938", - "metadata": { - "tags": [] - }, - "source": [ - "## 一、设置OpenAI API Key" - ] - }, - { - "cell_type": "markdown", - "id": "a2f5993b-f28d-4be4-984f-2d05be9f4579", - "metadata": {}, - "source": [ - "登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n", - "\n", - "- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n", - "- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n", - "\n", - "

\n", - " OPENAI_API_KEY=\"your_api_key\" \n", - "

\n", - " \n", - " 替换\"your_api_key\"为你自己的 API Key" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "adc3519c-4d12-4011-9223-2f3cb3c42b93", - "metadata": {}, - "outputs": [], - "source": [ - "# 下载需要的包python-dotenv和openai\n", - "# 如果你需要查看安装过程日志,可删除 -q \n", - "!pip install -q python-dotenv\n", - "!pip install -q openai" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "1ad53241-bef6-42b8-894b-bcbbc8c64df7", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import os\n", - "import openai\n", - "from dotenv import load_dotenv, find_dotenv\n", - "\n", - "# 读取本地/项目的环境变量。\n", - "\n", - "# find_dotenv()寻找并定位.env文件的路径\n", - "# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中 \n", - "# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n", - "_ = load_dotenv(find_dotenv())\n", - "\n", - "# 获取环境变量 OPENAI_API_KEY\n", - "openai.api_key = os.environ['OPENAI_API_KEY'] " - ] - }, - { - "cell_type": "markdown", - "id": "b940ce7c", - "metadata": { - "tags": [] - }, - "source": [ - "## 二、大语言模型链" - ] - }, - { - "cell_type": "markdown", - "id": "e000bd16", - "metadata": {}, - "source": [ - "大语言模型链(LLMChain)是一个简单但非常强大的链,也是后面我们将要介绍的许多链的基础。" - ] - }, - { - "cell_type": "markdown", - "id": "d57e93b9-52ba-4f86-a953-e4661b895a3d", - "metadata": {}, - "source": [ - "### 2.1 导入数据" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b84e441b", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install -q pandas" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "df = pd.read_csv('data/Data.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "b7a09c35", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
ProductReview
0Queen Size Sheet SetI ordered a king size set. My only criticism w...
1Waterproof Phone PouchI loved the waterproof sac, although the openi...
2Luxury Air MattressThis mattress had a small hole in the top of i...
3Pillows InsertThis is the best throw pillow fillers on Amazo...
4Milk Frother Handheld\\nI loved this product. But they only seem to l...
\n", - "
" - ], - "text/plain": [ - " Product Review\n", - "0 Queen Size Sheet Set I ordered a king size set. My only criticism w...\n", - "1 Waterproof Phone Pouch I loved the waterproof sac, although the openi...\n", - "2 Luxury Air Mattress This mattress had a small hole in the top of i...\n", - "3 Pillows Insert This is the best throw pillow fillers on Amazo...\n", - "4 Milk Frother Handheld\\n  I loved this product. But they only seem to l..." - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df.head()" - ] - }, - { - "cell_type": "markdown", - "id": "daa83d10-04ee-4355-abe3-ab699c9eaca9", - "metadata": {}, - "source": [ - "### 2.2 初始化语言模型" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "e92dff22", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import ChatOpenAI \n", - "from langchain.prompts import ChatPromptTemplate \n", - "from langchain.chains import LLMChain " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "943237a7", - "metadata": {}, - "outputs": [], - "source": [ - "# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。\n", - "# 如果你想要每次得到不一样的有新意的答案,可以尝试调整该参数。\n", - "llm = ChatOpenAI(temperature=0.0) " - ] - }, - { - "cell_type": "markdown", - "id": "81887434", - "metadata": {}, - "source": [ - "### 2.3 初始化提示模版\n", - "初始化提示,这个提示将接受一个名为product的变量。该prompt将要求LLM生成一个描述制造该产品的公司的最佳名称" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "cdcdb42d", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = ChatPromptTemplate.from_template( \n", - " \"What is the best name to describe \\\n", - " a company that makes {product}?\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "5c22cb13", - "metadata": {}, - "source": [ - "### 2.4 构建大语言模型链\n", - "\n", - "将大语言模型(LLM)和提示(Prompt)组合成链。这个大语言模型链非常简单,可以让我们以一种顺序的方式去通过运行提示并且结合到大语言模型中。" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "d7abc20b", - "metadata": {}, - "outputs": [], - "source": [ - "chain = LLMChain(llm=llm, prompt=prompt)" - ] - }, - { - "cell_type": "markdown", - "id": "8d7d5ff6", - "metadata": {}, - "source": [ - "### 2.5 运行大语言模型链\n", - "因此,如果我们有一个名为\"Queen Size Sheet Set\"的产品,我们可以通过使用chain.run将其通过这个链运行" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "ad44d1fb", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Royal Linens.'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "product = \"Queen Size Sheet Set\"\n", - "chain.run(product)" - ] - }, - { - "cell_type": "markdown", - "id": "1e1ede1c", - "metadata": {}, - "source": [ - "您可以输入任何产品描述,然后查看链将输出什么结果" - ] - }, - { - "cell_type": "markdown", - "id": "8ab31583-5cdf-4885-94d7-59c0d3b90b2e", - "metadata": {}, - "source": [ - "### 2.6 中文提示" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "2181be10", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\"豪华床纺\"'" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "prompt = ChatPromptTemplate.from_template( \n", - " \"描述制造{product}的一个公司的最佳名称是什么?\"\n", - ")\n", - "chain = LLMChain(llm=llm, prompt=prompt)\n", - "product = \"大号床单套装\"\n", - "chain.run(product)" - ] - }, - { - "cell_type": "markdown", - "id": "49158430", - "metadata": {}, - "source": [ - "## 三、顺序链" - ] - }, - { - "cell_type": "markdown", - "id": "69b03469", - "metadata": {}, - "source": [ - "### 3.1 简单顺序链\n", - "\n", - "顺序链(SequentialChains)是按预定义顺序执行其链接的链。具体来说,我们将使用简单顺序链(SimpleSequentialChain),这是顺序链的最简单类型,其中每个步骤都有一个输入/输出,一个步骤的输出是下一个步骤的输入。" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "febee243", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chains import SimpleSequentialChain" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "5d019d6f", - "metadata": {}, - "outputs": [], - "source": [ - "llm = ChatOpenAI(temperature=0.9)" - ] - }, - { - "cell_type": "markdown", - "id": "0e732589", - "metadata": {}, - "source": [ - "#### 3.1.1 创建两个子链" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "2f31aa8a", - "metadata": {}, - "outputs": [], - "source": [ - "# 提示模板 1 :这个提示将接受产品并返回最佳名称来描述该公司\n", - "first_prompt = ChatPromptTemplate.from_template(\n", - " \"What is the best name to describe \\\n", - " a company that makes {product}?\"\n", - ")\n", - "\n", - "# Chain 1\n", - "chain_one = LLMChain(llm=llm, prompt=first_prompt)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "3f5d5b76", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "# 提示模板 2 :接受公司名称,然后输出该公司的长为20个单词的描述\n", - "second_prompt = ChatPromptTemplate.from_template(\n", - " \"Write a 20 words description for the following \\\n", - " company:{company_name}\"\n", - ")\n", - "# chain 2\n", - "chain_two = LLMChain(llm=llm, prompt=second_prompt)" - ] - }, - { - "cell_type": "markdown", - "id": "3a1991f4", - "metadata": {}, - "source": [ - "#### 3.1.2 构建简单顺序链\n", - "现在我们可以组合两个LLMChain,以便我们可以在一个步骤中创建公司名称和描述" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "6c1eb2c4", - "metadata": {}, - "outputs": [], - "source": [ - "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two], verbose=True)" - ] - }, - { - "cell_type": "markdown", - "id": "5122f26a", - "metadata": {}, - "source": [ - "给一个输入,然后运行上面的链" - ] - }, - { - "cell_type": "markdown", - "id": "9a80d102-da6b-49f4-8abd-7bff97211232", - "metadata": {}, - "source": [ - "#### 3.1.3 运行简单顺序链" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "78458efe", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "\u001b[36;1m\u001b[1;3mRoyal Rest Linens\u001b[0m\n", - "\u001b[33;1m\u001b[1;3mRoyal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "\"Royal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\"" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "product = \"Queen Size Sheet Set\"\n", - "overall_simple_chain.run(product)" - ] - }, - { - "cell_type": "markdown", - "id": "3983eb68-adf0-4c18-beed-ff6fc09cd78b", - "metadata": {}, - "source": [ - "#### 3.1.4 中文提示" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "c7c32997", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", - "\u001b[36;1m\u001b[1;3m\"尺寸王床品有限公司\"\u001b[0m\n", - "\u001b[33;1m\u001b[1;3m尺寸王床品有限公司是一家专注于床上用品生产的公司。\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'尺寸王床品有限公司是一家专注于床上用品生产的公司。'" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 中文\n", - "\n", - "first_prompt = ChatPromptTemplate.from_template( \n", - " \"描述制造{product}的一个公司的最好的名称是什么\"\n", - ")\n", - "chain_one = LLMChain(llm=llm, prompt=first_prompt)\n", - "\n", - "second_prompt = ChatPromptTemplate.from_template( \n", - " \"写一个20字的描述对于下面这个\\\n", - " 公司:{company_name}的\"\n", - ")\n", - "chain_two = LLMChain(llm=llm, prompt=second_prompt)\n", - "\n", - "\n", - "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],verbose=True)\n", - "product = \"大号床单套装\"\n", - "overall_simple_chain.run(product)" - ] - }, - { - "cell_type": "markdown", - "id": "7b5ce18c", - "metadata": {}, - "source": [ - "### 3.2 顺序链" - ] - }, - { - "cell_type": "markdown", - "id": "1e69f4c0", - "metadata": {}, - "source": [ - "当只有一个输入和一个输出时,简单顺序链(SimpleSequentialChain)即可实现。当有多个输入或多个输出时,我们则需要使用顺序链(SequentialChain)来实现。" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "4c129ef6", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chains import SequentialChain\n", - "from langchain.chat_models import ChatOpenAI #导入OpenAI模型\n", - "from langchain.prompts import ChatPromptTemplate #导入聊天提示模板\n", - "from langchain.chains import LLMChain #导入LLM链。" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "03a8e203", - "metadata": {}, - "outputs": [], - "source": [ - "llm = ChatOpenAI(temperature=0.9)" - ] - }, - { - "cell_type": "markdown", - "id": "9811445c", - "metadata": {}, - "source": [ - "接下来我们将创建一系列的链,然后一个接一个使用他们" - ] - }, - { - "cell_type": "markdown", - "id": "df9e87ec-b99a-4130-a5b5-cdce064dc6ca", - "metadata": {}, - "source": [ - "#### 3.2.1 创建四个子链" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "016187ac", - "metadata": {}, - "outputs": [], - "source": [ - "#子链1\n", - "\n", - "# prompt模板 1: 翻译成英语(把下面的review翻译成英语)\n", - "first_prompt = ChatPromptTemplate.from_template(\n", - " \"Translate the following review to english:\"\n", - " \"\\n\\n{Review}\"\n", - ")\n", - "# chain 1: 输入:Review 输出: 英文的 Review\n", - "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "0fb0730e", - "metadata": {}, - "outputs": [], - "source": [ - "#子链2\n", - "\n", - "# prompt模板 2: 用一句话总结下面的 review\n", - "second_prompt = ChatPromptTemplate.from_template(\n", - " \"Can you summarize the following review in 1 sentence:\"\n", - " \"\\n\\n{English_Review}\"\n", - ")\n", - "# chain 2: 输入:英文的Review 输出:总结\n", - "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "6accf92d", - "metadata": {}, - "outputs": [], - "source": [ - "#子链3\n", - "\n", - "# prompt模板 3: 下面review使用的什么语言\n", - "third_prompt = ChatPromptTemplate.from_template(\n", - " \"What language is the following review:\\n\\n{Review}\"\n", - ")\n", - "# chain 3: 输入:Review 输出:语言\n", - "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "c7a46121", - "metadata": {}, - "outputs": [], - "source": [ - "#子链4\n", - "\n", - "# prompt模板 4: 使用特定的语言对下面的总结写一个后续回复\n", - "fourth_prompt = ChatPromptTemplate.from_template(\n", - " \"Write a follow up response to the following \"\n", - " \"summary in the specified language:\"\n", - " \"\\n\\nSummary: {summary}\\n\\nLanguage: {language}\"\n", - ")\n", - "# chain 4: 输入: 总结, 语言 输出: 后续回复\n", - "chain_four = LLMChain(llm=llm, prompt=fourth_prompt, output_key=\"followup_message\")\n" - ] - }, - { - "cell_type": "markdown", - "id": "ff435291-5d20-4c3e-9ed7-76a1140f96d2", - "metadata": {}, - "source": [ - "#### 3.2.2 对四个子链进行组合" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "89603117", - "metadata": {}, - "outputs": [], - "source": [ - "#输入:review \n", - "#输出:英文review,总结,后续回复 \n", - "overall_chain = SequentialChain(\n", - " chains=[chain_one, chain_two, chain_three, chain_four],\n", - " input_variables=[\"Review\"],\n", - " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", - " verbose=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "0509de01", - "metadata": {}, - "source": [ - "让我们选择一篇评论并通过整个链传递它,可以发现,原始review是法语,可以把英文review看做是一种翻译,接下来是根据英文review得到的总结,最后输出的是用法语原文进行的续写信息。" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "51b04f45", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "{'Review': \"Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\\nVieux lot ou contrefaçon !?\",\n", - " 'English_Review': \"I find the taste mediocre. The foam doesn't hold, it's weird. I buy the same ones in the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", - " 'summary': 'The reviewer is disappointed with the taste and consistency of the product, suspecting that either an old batch or counterfeit version is the cause.',\n", - " 'followup_message': \"Réponse de suivi :\\n\\nCher(e) critique,\\n\\nNous sommes désolés d'apprendre que notre produit ne répond pas à vos attentes. Nous prenons très au sérieux les commentaires de nos clients et nous tenons à vous rassurer que nous attachons une grande importance à la qualité de nos produits.\\n\\nNous vérifions constamment nos processus de production afin de nous assurer que nos produits sont toujours frais et authentiques. Si vous pensez avoir reçu un produit contrefait ou un lot périmé, nous vous prions de nous contacter directement afin de résoudre ce problème au plus vite. Nous avons un service client dédié qui sera ravi de vous aider avec votre préoccupation.\\n\\nNous tenons à nous excuser pour toute déception ou désagrément que cela aurait pu causer. Votre satisfaction est notre priorité absolue et nous ferons tout notre possible pour remédier à la situation et regagner votre confiance.\\n\\nNous vous remercions de votre compréhension et de votre patience. Votre avis est important pour nous et nous espérons avoir l'occasion de nous rattraper à l'avenir.\\n\\nCordialement,\\nL'équipe de [Nom de l'entreprise]\"}" - ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "review = df.Review[5]\n", - "overall_chain(review)" - ] - }, - { - "cell_type": "markdown", - "id": "18d72f1d-8a1e-4eb6-b00f-1963b3cf3adb", - "metadata": {}, - "source": [ - "#### 3.2.3 中文提示" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "31624a7c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new chain...\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "{'Review': \"Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\\nVieux lot ou contrefaçon !?\",\n", - " 'English_Review': \"I find the taste mediocre. The foam doesn't last, it's weird. I buy the same ones from the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", - " 'summary': \"The taste is mediocre, the foam doesn't last, and there is suspicion of old batch or counterfeit.\",\n", - " 'followup_message': \"回复: Je suis désolé de vous entendre dire que le goût est moyen et que la mousse ne dure pas longtemps. Nous prenons ces problèmes très au sérieux. Nous allons enquêter pour vérifier s'il s'agit d'un ancien lot ou d'une contrefaçon. Votre satisfaction est notre priorité et nous ferons de notre mieux pour résoudre ce problème. Merci de nous avoir informés.\"}" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 中文\n", - "\n", - "#子链1\n", - "# prompt模板 1: 翻译成英语(把下面的review翻译成英语)\n", - "first_prompt = ChatPromptTemplate.from_template(\n", - " \"把下面的评论review翻译成英文:\"\n", - " \"\\n\\n{Review}\"\n", - ")\n", - "# chain 1: 输入:Review 输出:英文的 Review\n", - "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")\n", - "\n", - "#子链2\n", - "# prompt模板 2: 用一句话总结下面的 review\n", - "second_prompt = ChatPromptTemplate.from_template(\n", - " \"请你用一句话来总结下面的评论review:\"\n", - " \"\\n\\n{English_Review}\"\n", - ")\n", - "# chain 2: 输入:英文的Review 输出:总结\n", - "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n", - "\n", - "\n", - "#子链3\n", - "# prompt模板 3: 下面review使用的什么语言\n", - "third_prompt = ChatPromptTemplate.from_template(\n", - " \"下面的评论review使用的什么语言:\\n\\n{Review}\"\n", - ")\n", - "# chain 3: 输入:Review 输出:语言\n", - "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n", - "\n", - "\n", - "#子链4\n", - "# prompt模板 4: 使用特定的语言对下面的总结写一个后续回复\n", - "fourth_prompt = ChatPromptTemplate.from_template(\n", - " \"使用特定的语言对下面的总结写一个后续回复:\"\n", - " \"\\n\\n总结: {summary}\\n\\n语言: {language}\"\n", - ")\n", - "# chain 4: 输入: 总结, 语言 输出: 后续回复\n", - "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n", - " output_key=\"followup_message\"\n", - " )\n", - "\n", - "\n", - "# 对四个子链进行组合\n", - "#输入:review 输出:英文review,总结,后续回复 \n", - "overall_chain = SequentialChain(\n", - " chains=[chain_one, chain_two, chain_three, chain_four],\n", - " input_variables=[\"Review\"],\n", - " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", - " verbose=True\n", - ")\n", - "\n", - "\n", - "review = df.Review[5]\n", - "overall_chain(review)" - ] - }, - { - "cell_type": "markdown", - "id": "3041ea4c", - "metadata": {}, - "source": [ - "## 四、 路由链" - ] - }, - { - "cell_type": "markdown", - "id": "f0c32f97", - "metadata": {}, - "source": [ - "到目前为止,我们已经学习了大语言模型链和顺序链。但是,如果我们想做一些更复杂的事情怎么办?\n", - "\n", - "一个相当常见但基本的操作是根据输入将其路由到一条链,具体取决于该输入到底是什么。如果你有多个子链,每个子链都专门用于特定类型的输入,那么可以组成一个路由链,它首先决定将它传递给哪个子链,然后将它传递给那个链。\n", - "\n", - "路由器由两个组件组成:\n", - "\n", - "- 路由链(Router Chain):路由器链本身,负责选择要调用的下一个链\n", - "- destination_chains:路由器链可以路由到的链\n", - "\n", - "举一个具体的例子,让我们看一下我们在不同类型的链之间路由的地方,我们在这里有不同的prompt: " - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "31b06fc8", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chains.router import MultiPromptChain #导入多提示链\n", - "from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser\n", - "from langchain.prompts import PromptTemplate" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "f3f50bcc", - "metadata": {}, - "outputs": [], - "source": [ - "llm = ChatOpenAI(temperature=0)" - ] - }, - { - "cell_type": "markdown", - "id": "cb1b4708", - "metadata": {}, - "source": [ - "### 4.1 定义提示模板" - ] - }, - { - "cell_type": "markdown", - "id": "c3b85285-c736-4a5d-bd14-d9b5025ca29b", - "metadata": {}, - "source": [ - "首先,我们定义提示适用于不同场景下的提示模板。" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "ade83f4f", - "metadata": {}, - "outputs": [], - "source": [ - "#第一个提示适合回答物理问题\n", - "physics_template = \"\"\"You are a very smart physics professor. \\\n", - "You are great at answering questions about physics in a concise\\\n", - "and easy to understand manner. \\\n", - "When you don't know the answer to a question you admit\\\n", - "that you don't know.\n", - "\n", - "Here is a question:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第二个提示适合回答数学问题\n", - "math_template = \"\"\"You are a very good mathematician. \\\n", - "You are great at answering math questions. \\\n", - "You are so good because you are able to break down \\\n", - "hard problems into their component parts, \n", - "answer the component parts, and then put them together\\\n", - "to answer the broader question.\n", - "\n", - "Here is a question:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第三个适合回答历史问题\n", - "history_template = \"\"\"You are a very good historian. \\\n", - "You have an excellent knowledge of and understanding of people,\\\n", - "events and contexts from a range of historical periods. \\\n", - "You have the ability to think, reflect, debate, discuss and \\\n", - "evaluate the past. You have a respect for historical evidence\\\n", - "and the ability to make use of it to support your explanations \\\n", - "and judgements.\n", - "\n", - "Here is a question:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第四个适合回答计算机问题\n", - "computerscience_template = \"\"\" You are a successful computer scientist.\\\n", - "You have a passion for creativity, collaboration,\\\n", - "forward-thinking, confidence, strong problem-solving capabilities,\\\n", - "understanding of theories and algorithms, and excellent communication \\\n", - "skills. You are great at answering coding questions. \\\n", - "You are so good because you know how to solve a problem by \\\n", - "describing the solution in imperative steps \\\n", - "that a machine can easily interpret and you know how to \\\n", - "choose a solution that has a good balance between \\\n", - "time complexity and space complexity. \n", - "\n", - "Here is a question:\n", - "{input}\"\"\"" - ] - }, - { - "cell_type": "markdown", - "id": "cb3b749b-0d3c-46f2-afab-b1213f208b13", - "metadata": {}, - "source": [ - "### 4.2 对提示模版进行命名和描述" - ] - }, - { - "cell_type": "markdown", - "id": "6922b35e", - "metadata": {}, - "source": [ - "在定义了这些提示模板后,我们可以为每个模板命名,并给出具体描述。例如,第一个物理学的描述适合回答关于物理学的问题,这些信息将传递给路由链,然后由路由链决定何时使用此子链。" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "141a3d32", - "metadata": {}, - "outputs": [], - "source": [ - "prompt_infos = [\n", - " {\n", - " \"name\": \"physics\", \n", - " \"description\": \"Good for answering questions about physics\", \n", - " \"prompt_template\": physics_template\n", - " },\n", - " {\n", - " \"name\": \"math\", \n", - " \"description\": \"Good for answering math questions\", \n", - " \"prompt_template\": math_template\n", - " },\n", - " {\n", - " \"name\": \"History\", \n", - " \"description\": \"Good for answering history questions\", \n", - " \"prompt_template\": history_template\n", - " },\n", - " {\n", - " \"name\": \"computer science\", \n", - " \"description\": \"Good for answering computer science questions\", \n", - " \"prompt_template\": computerscience_template\n", - " }\n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "8795cd42", - "metadata": {}, - "source": [ - "LLMRouterChain(此链使用 LLM 来确定如何路由事物)\n", - "\n", - "在这里,我们需要一个**多提示链**。这是一种特定类型的链,用于在多个不同的提示模板之间进行路由。 但是这只是路由的一种类型,我们也可以在任何类型的链之间进行路由。\n", - "\n", - "这里我们要实现的几个类是大模型路由器链。这个类本身使用语言模型来在不同的子链之间进行路由。这就是上面提供的描述和名称将被使用的地方。" - ] - }, - { - "cell_type": "markdown", - "id": "46633b43", - "metadata": {}, - "source": [ - "### 4.3 基于提示模版信息创建相应目标链 \n", - "目标链是由路由链调用的链,每个目标链都是一个语言模型链" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "8eefec24", - "metadata": {}, - "outputs": [], - "source": [ - "destination_chains = {}\n", - "for p_info in prompt_infos:\n", - " name = p_info[\"name\"]\n", - " prompt_template = p_info[\"prompt_template\"]\n", - " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", - " chain = LLMChain(llm=llm, prompt=prompt)\n", - " destination_chains[name] = chain \n", - " \n", - "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n", - "destinations_str = \"\\n\".join(destinations)" - ] - }, - { - "cell_type": "markdown", - "id": "eba115de", - "metadata": { - "tags": [] - }, - "source": [ - "### 4.4 创建默认目标链\n", - "除了目标链之外,我们还需要一个默认目标链。这是一个当路由器无法决定使用哪个子链时调用的链。在上面的示例中,当输入问题与物理、数学、历史或计算机科学无关时,可能会调用它。" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "9f98018a", - "metadata": {}, - "outputs": [], - "source": [ - "default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", - "default_chain = LLMChain(llm=llm, prompt=default_prompt)" - ] - }, - { - "cell_type": "markdown", - "id": "948700c4", - "metadata": {}, - "source": [ - "### 4.5 定义不同链之间的路由模板\n", - "\n", - "这包括要完成的任务的说明以及输出应该采用的特定格式。" - ] - }, - { - "cell_type": "markdown", - "id": "24f30c2c", - "metadata": {}, - "source": [ - "注意:此处在原教程的基础上添加了一个示例,主要是因为\"gpt-3.5-turbo\"模型不能很好适应理解模板的意思,使用 \"text-davinci-003\" 或者\"gpt-4-0613\"可以很好的工作,因此在这里多加了示例提示让其更好的学习。\n", - "eg:\n", - "<< INPUT >>\n", - "\"What is black body radiation?\"\n", - "<< OUTPUT >>\n", - "```json\n", - "{{{{\n", - " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", - " \"next_inputs\": string \\ a potentially modified version of the original input\n", - "}}}}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "11b2e2ba", - "metadata": {}, - "outputs": [], - "source": [ - "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"Given a raw text input to a \\\n", - "language model select the model prompt best suited for the input. \\\n", - "You will be given the names of the available prompts and a \\\n", - "description of what the prompt is best suited for. \\\n", - "You may also revise the original input if you think that revising\\\n", - "it will ultimately lead to a better response from the language model.\n", - "\n", - "<< FORMATTING >>\n", - "Return a markdown code snippet with a JSON object formatted to look like:\n", - "```json\n", - "{{{{\n", - " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", - " \"next_inputs\": string \\ a potentially modified version of the original input\n", - "}}}}\n", - "```\n", - "\n", - "REMEMBER: \"destination\" MUST be one of the candidate prompt \\\n", - "names specified below OR it can be \"DEFAULT\" if the input is not\\\n", - "well suited for any of the candidate prompts.\n", - "REMEMBER: \"next_inputs\" can just be the original input \\\n", - "if you don't think any modifications are needed.\n", - "\n", - "<< CANDIDATE PROMPTS >>\n", - "{destinations}\n", - "\n", - "<< INPUT >>\n", - "{{input}}\n", - "\n", - "<< OUTPUT (remember to include the ```json)>>\n", - "\n", - "eg:\n", - "<< INPUT >>\n", - "\"What is black body radiation?\"\n", - "<< OUTPUT >>\n", - "```json\n", - "{{{{\n", - " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", - " \"next_inputs\": string \\ a potentially modified version of the original input\n", - "}}}}\n", - "```\n", - "\n", - "\"\"\"" - ] - }, - { - "cell_type": "markdown", - "id": "de5c46d0", - "metadata": {}, - "source": [ - "### 4.6 构建路由链\n", - "首先,我们通过格式化上面定义的目标创建完整的路由器模板。这个模板可以适用许多不同类型的目标。\n", - "因此,在这里,您可以添加一个不同的学科,如英语或拉丁语,而不仅仅是物理、数学、历史和计算机科学。\n", - "\n", - "接下来,我们从这个模板创建提示模板\n", - "\n", - "最后,通过传入llm和整个路由提示来创建路由链。需要注意的是这里有路由输出解析,这很重要,因为它将帮助这个链路决定在哪些子链路之间进行路由。" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "1387109d", - "metadata": {}, - "outputs": [], - "source": [ - "router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(\n", - " destinations=destinations_str\n", - ")\n", - "router_prompt = PromptTemplate(\n", - " template=router_template,\n", - " input_variables=[\"input\"],\n", - " output_parser=RouterOutputParser(),\n", - ")\n", - "\n", - "router_chain = LLMRouterChain.from_llm(llm, router_prompt)" - ] - }, - { - "cell_type": "markdown", - "id": "7e92355c", - "metadata": {}, - "source": [ - "### 4.7 创建整体链路" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "2fb7d560", - "metadata": {}, - "outputs": [], - "source": [ - "#多提示链\n", - "chain = MultiPromptChain(router_chain=router_chain, #l路由链路\n", - " destination_chains=destination_chains, #目标链路\n", - " default_chain=default_chain, #默认链路\n", - " verbose=True \n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "086503f7", - "metadata": {}, - "source": [ - "### 4.8 进行提问" - ] - }, - { - "cell_type": "markdown", - "id": "969cd878", - "metadata": {}, - "source": [ - "如果我们问一个物理问题,我们希望看到他被路由到物理链路" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2217d987", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "physics: {'input': 'What is black body radiation?'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'Black body radiation is the electromagnetic radiation emitted by a perfect black body, which absorbs all incident radiation and reflects none. It is characterized by a continuous spectrum of radiated energy that is dependent on the temperature of the body, with higher temperatures leading to more intense and shorter wavelength radiation. This phenomenon is an important concept in thermal physics and has numerous applications, ranging from understanding stellar spectra to designing artificial light sources.'" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# 问题:什么是黑体辐射?\n", - "chain.run(\"What is black body radiation?\")" - ] - }, - { - "cell_type": "markdown", - "id": "289c5ca9", - "metadata": {}, - "source": [ - "如果我们问一个数学问题,我们希望看到他被路由到数学链路" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "3b717379", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "math: {'input': 'what is 2 + 2'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'As an AI language model, I can answer this question. The answer to 2 + 2 is 4.'" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 问题:2+2等于多少?\n", - "chain.run(\"what is 2 + 2\")" - ] - }, - { - "cell_type": "markdown", - "id": "4186a2b9", - "metadata": {}, - "source": [ - "如果我们传递一个与任何子链路都无关的问题时,会发生什么呢?\n", - "\n", - "这里,我们问了一个关于生物学的问题,我们可以看到它选择的链路是无。这意味着它将被**传递到默认链路,它本身只是对语言模型的通用调用**。语言模型幸运地对生物学知道很多,所以它可以帮助我们。" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "29e5be01", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "None: {'input': 'Why does every cell in our body contain DNA?'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'Every cell in our body contains DNA because DNA carries the genetic information that determines the characteristics and functions of each cell. DNA contains the instructions for the synthesis of proteins, which are essential for the structure and function of cells. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next. Therefore, every cell in our body needs DNA to carry out its specific functions and to maintain the integrity of the organism as a whole.'" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 问题:为什么我们身体里的每个细胞都包含DNA?\n", - "chain.run(\"Why does every cell in our body contain DNA?\")" - ] - }, - { - "cell_type": "markdown", - "id": "753b5f1d-b010-4f33-a928-d3b9e85bf289", - "metadata": {}, - "source": [ - "### 4.9 中文提示" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "id": "f7fade7a", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "#第一个提示适合回答物理问题\n", - "physics_template = \"\"\"你是一个非常聪明的物理专家。 \\\n", - "你擅长用一种简洁并且易于理解的方式去回答问题。\\\n", - "当你不知道问题的答案时,你承认\\\n", - "你不知道.\n", - "\n", - "这是一个问题:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第二个提示适合回答数学问题\n", - "math_template = \"\"\"你是一个非常优秀的数学家。 \\\n", - "你擅长回答数学问题。 \\\n", - "你之所以如此优秀, \\\n", - "是因为你能够将棘手的问题分解为组成部分,\\\n", - "回答组成部分,然后将它们组合在一起,回答更广泛的问题。\n", - "\n", - "这是一个问题:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第三个适合回答历史问题\n", - "history_template = \"\"\"你是以为非常优秀的历史学家。 \\\n", - "你对一系列历史时期的人物、事件和背景有着极好的学识和理解\\\n", - "你有能力思考、反思、辩证、讨论和评估过去。\\\n", - "你尊重历史证据,并有能力利用它来支持你的解释和判断。\n", - "\n", - "这是一个问题:\n", - "{input}\"\"\"\n", - "\n", - "\n", - "#第四个适合回答计算机问题\n", - "computerscience_template = \"\"\" 你是一个成功的计算机科学专家。\\\n", - "你有创造力、协作精神、\\\n", - "前瞻性思维、自信、解决问题的能力、\\\n", - "对理论和算法的理解以及出色的沟通技巧。\\\n", - "你非常擅长回答编程问题。\\\n", - "你之所以如此优秀,是因为你知道 \\\n", - "如何通过以机器可以轻松解释的命令式步骤描述解决方案来解决问题,\\\n", - "并且你知道如何选择在时间复杂性和空间复杂性之间取得良好平衡的解决方案。\n", - "\n", - "这还是一个输入:\n", - "{input}\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "id": "deb8aafc", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "prompt_infos = [\n", - " {\n", - " \"名字\": \"物理学\", \n", - " \"描述\": \"擅长回答关于物理学的问题\", \n", - " \"提示模板\": physics_template\n", - " },\n", - " {\n", - " \"名字\": \"数学\", \n", - " \"描述\": \"擅长回答数学问题\", \n", - " \"提示模板\": math_template\n", - " },\n", - " {\n", - " \"名字\": \"历史\", \n", - " \"描述\": \"擅长回答历史问题\", \n", - " \"提示模板\": history_template\n", - " },\n", - " {\n", - " \"名字\": \"计算机科学\", \n", - " \"描述\": \"擅长回答计算机科学问题\", \n", - " \"提示模板\": computerscience_template\n", - " }\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fd6eb641", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "destination_chains = {}\n", - "for p_info in prompt_infos:\n", - " name = p_info[\"名字\"]\n", - " prompt_template = p_info[\"提示模板\"]\n", - " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", - " chain = LLMChain(llm=llm, prompt=prompt)\n", - " destination_chains[name] = chain \n", - " \n", - "destinations = [f\"{p['名字']}: {p['描述']}\" for p in prompt_infos]\n", - "destinations_str = \"\\n\".join(destinations)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "af088d6b-a70b-4cd7-bc6e-4ad7b32e6ae1", - "metadata": {}, - "outputs": [], - "source": [ - "default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", - "default_chain = LLMChain(llm=llm, prompt=default_prompt)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a7aae035", - "metadata": {}, - "outputs": [], - "source": [ - "# 中文\n", - "\n", - "# 多提示路由模板\n", - "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"给语言模型一个原始文本输入,\\\n", - "让其选择最适合输入的模型提示。\\\n", - "系统将为您提供可用提示的名称以及最适合改提示的描述。\\\n", - "如果你认为修改原始输入最终会导致语言模型做出更好的响应,\\\n", - "你也可以修改原始输入。\n", - "\n", - "\n", - "<< 格式 >>\n", - "返回一个带有JSON对象的markdown代码片段,该JSON对象的格式如下:\n", - "```json\n", - "{{{{\n", - " \"destination\": 字符串 \\ 使用的提示名字或者使用 \"DEFAULT\"\n", - " \"next_inputs\": 字符串 \\ 原始输入的改进版本\n", - "}}}}\n", - "```\n", - "\n", - "\n", - "记住:“destination”必须是下面指定的候选提示名称之一,\\\n", - "或者如果输入不太适合任何候选提示,\\\n", - "则可以是 “DEFAULT” 。\n", - "记住:如果您认为不需要任何修改,\\\n", - "则 “next_inputs” 可以只是原始输入。\n", - "\n", - "<< 候选提示 >>\n", - "{destinations}\n", - "\n", - "<< 输入 >>\n", - "{{input}}\n", - "\n", - "<< 输出 (记得要包含 ```json)>>\n", - "\n", - "样例:\n", - "<< 输入 >>\n", - "\"什么是黑体辐射?\"\n", - "<< 输出 >>\n", - "```json\n", - "{{{{\n", - " \"destination\": 字符串 \\ 使用的提示名字或者使用 \"DEFAULT\"\n", - " \"next_inputs\": 字符串 \\ 原始输入的改进版本\n", - "}}}}\n", - "```\n", - "\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7470b25c-ef82-496c-a6e0-e04b99b08e70", - "metadata": {}, - "outputs": [], - "source": [ - "#多提示链\n", - "chain = MultiPromptChain(router_chain=router_chain, #l路由链路\n", - " destination_chains=destination_chains, #目标链路\n", - " default_chain=default_chain, #默认链路\n", - " verbose=True \n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "4446724c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "physics: {'input': '什么是黑体辐射?'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'黑体辐射是指一个理想化的物体,它能够完全吸收所有入射到它表面的辐射能量,并以热辐射的形式重新发射出来。黑体辐射的特点是其辐射能量的分布与温度有关,随着温度的升高,辐射能量的峰值会向更短的波长方向移动。这个现象被称为黑体辐射谱的位移定律,由普朗克在20世纪初提出。黑体辐射在研究热力学、量子力学和宇宙学等领域中具有重要的应用。'" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#中文\n", - "chain.run(\"什么是黑体辐射?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "ef81eda3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "History: {'input': '你知道李白是谁嘛?'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'李白是唐朝时期的一位著名诗人。他的诗歌以豪放、奔放、自由的风格著称,被誉为“诗仙”。他的作品涉及广泛,包括山水田园、历史传说、哲理思考等多个方面,对中国古典文学的发展产生了深远的影响。'" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 中文\n", - "chain.run(\"你知道李白是谁嘛?\")" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "795bea17", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "math: {'input': '2 + 2 等于多少'}" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised ServiceUnavailableError: The server is overloaded or not ready yet..\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'2 + 2 等于 4。'" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 中文\n", - "chain.run(\"2 + 2 等于多少\")" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "a64d0759", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", - "None: {'input': '为什么我们身体里的每个细胞都包含DNA?'}\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'我们身体里的每个细胞都包含DNA,是因为DNA是遗传信息的载体。DNA是由四种碱基(腺嘌呤、鸟嘌呤、胸腺嘧啶和鳞嘌呤)组成的长链状分子,它存储了生物体的遗传信息,包括个体的特征、生长发育、代谢功能等。每个细胞都需要这些遗传信息来执行其特定的功能和任务,因此每个细胞都需要包含DNA。此外,DNA还能通过复制和传递给下一代细胞和个体,以保证遗传信息的传承。'" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# 中文\n", - "chain.run(\"为什么我们身体里的每个细胞都包含DNA?\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{"cells": [{"cell_type": "markdown", "id": "52824b89-532a-4e54-87e9-1410813cd39e", "metadata": {}, "source": ["# \u7b2c\u56db\u7ae0 \u6a21\u578b\u94fe\n", "\n", " - [\u4e00\u3001\u8bbe\u7f6eOpenAI API Key](#\u4e00\u3001\u8bbe\u7f6eOpenAI-API-Key)\n", " - [\u4e8c\u3001\u5927\u8bed\u8a00\u6a21\u578b\u94fe](#\u4e8c\u3001\u5927\u8bed\u8a00\u6a21\u578b\u94fe)\n", " - [2.1 \u5bfc\u5165\u6570\u636e](#2.1-\u5bfc\u5165\u6570\u636e)\n", " - [2.2 \u521d\u59cb\u5316\u8bed\u8a00\u6a21\u578b](#2.2-\u521d\u59cb\u5316\u8bed\u8a00\u6a21\u578b)\n", " - [2.3 \u521d\u59cb\u5316\u63d0\u793a\u6a21\u7248](#2.3-\u521d\u59cb\u5316\u63d0\u793a\u6a21\u7248)\n", " - [2.4 \u6784\u5efa\u5927\u8bed\u8a00\u6a21\u578b\u94fe](#2.4-\u6784\u5efa\u5927\u8bed\u8a00\u6a21\u578b\u94fe)\n", " - [2.5 \u8fd0\u884c\u5927\u8bed\u8a00\u6a21\u578b\u94fe](#2.5-\u8fd0\u884c\u5927\u8bed\u8a00\u6a21\u578b\u94fe)\n", " - [2.6 \u4e2d\u6587\u63d0\u793a](#2.6-\u4e2d\u6587\u63d0\u793a)\n", " - [\u4e09\u3001\u987a\u5e8f\u94fe](#\u4e09\u3001\u987a\u5e8f\u94fe)\n", " - [3.1 \u7b80\u5355\u987a\u5e8f\u94fe](#3.1-\u7b80\u5355\u987a\u5e8f\u94fe)\n", " - [3.1.1 \u521b\u5efa\u4e24\u4e2a\u5b50\u94fe](#3.1.1-\u521b\u5efa\u4e24\u4e2a\u5b50\u94fe)\n", " - [3.1.2 \u6784\u5efa\u7b80\u5355\u987a\u5e8f\u94fe](#3.1.2-\u6784\u5efa\u7b80\u5355\u987a\u5e8f\u94fe)\n", " - [3.1.3 \u8fd0\u884c\u7b80\u5355\u987a\u5e8f\u94fe](#3.1.3-\u8fd0\u884c\u7b80\u5355\u987a\u5e8f\u94fe)\n", " - [3.1.4 \u4e2d\u6587\u63d0\u793a](#3.1.4-\u4e2d\u6587\u63d0\u793a)\n", " - [3.2 \u987a\u5e8f\u94fe](#3.2-\u987a\u5e8f\u94fe)\n", " - [3.2.1 \u521b\u5efa\u56db\u4e2a\u5b50\u94fe](#3.2.1-\u521b\u5efa\u56db\u4e2a\u5b50\u94fe)\n", " - [3.2.2 \u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408](#3.2.2-\u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408)\n", " - [3.2.3 \u4e2d\u6587\u63d0\u793a](#3.2.3-\u4e2d\u6587\u63d0\u793a)\n", " - [\u56db\u3001 \u8def\u7531\u94fe](#\u56db\u3001-\u8def\u7531\u94fe)\n", " - [4.1 \u5b9a\u4e49\u63d0\u793a\u6a21\u677f](#4.1-\u5b9a\u4e49\u63d0\u793a\u6a21\u677f)\n", " - [4.2 \u5bf9\u63d0\u793a\u6a21\u7248\u8fdb\u884c\u547d\u540d\u548c\u63cf\u8ff0](#4.2-\u5bf9\u63d0\u793a\u6a21\u7248\u8fdb\u884c\u547d\u540d\u548c\u63cf\u8ff0)\n", " - [4.3 \u57fa\u4e8e\u63d0\u793a\u6a21\u7248\u4fe1\u606f\u521b\u5efa\u76f8\u5e94\u76ee\u6807\u94fe ](#4.3-\u57fa\u4e8e\u63d0\u793a\u6a21\u7248\u4fe1\u606f\u521b\u5efa\u76f8\u5e94\u76ee\u6807\u94fe--)\n", " - [4.4 \u521b\u5efa\u9ed8\u8ba4\u76ee\u6807\u94fe](#4.4-\u521b\u5efa\u9ed8\u8ba4\u76ee\u6807\u94fe)\n", " - [4.5 \u5b9a\u4e49\u4e0d\u540c\u94fe\u4e4b\u95f4\u7684\u8def\u7531\u6a21\u677f](#4.5-\u5b9a\u4e49\u4e0d\u540c\u94fe\u4e4b\u95f4\u7684\u8def\u7531\u6a21\u677f)\n", " - [4.6 \u6784\u5efa\u8def\u7531\u94fe](#4.6-\u6784\u5efa\u8def\u7531\u94fe)\n", " - [4.7 \u521b\u5efa\u6574\u4f53\u94fe\u8def](#4.7-\u521b\u5efa\u6574\u4f53\u94fe\u8def)\n", " - [4.8 \u8fdb\u884c\u63d0\u95ee](#4.8-\u8fdb\u884c\u63d0\u95ee)\n", " - [4.9 \u4e2d\u6587\u63d0\u793a](#4.9-\u4e2d\u6587\u63d0\u793a)\n"]}, {"cell_type": "markdown", "id": "54810ef7", "metadata": {}, "source": ["\u94fe\uff08Chains\uff09\u901a\u5e38\u5c06\u5927\u8bed\u8a00\u6a21\u578b\uff08LLM\uff09\u4e0e\u63d0\u793a(Prompt)\u7ed3\u5408\u5728\u4e00\u8d77\uff0c\u57fa\u4e8e\u6b64\uff0c\u6211\u4eec\u53ef\u4ee5\u5bf9\u6587\u672c\u6216\u6570\u636e\u8fdb\u884c\u4e00\u7cfb\u5217\u64cd\u4f5c\u3002\n", "\n", "\u94fe\uff08Chains\uff09\u53ef\u4ee5\u4e00\u6b21\u6027\u63a5\u53d7\u591a\u4e2a\u8f93\u5165\n", "\n", "\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u94fe\uff0c\u8be5\u94fe\u63a5\u53d7\u7528\u6237\u8f93\u5165\uff0c\u4f7f\u7528\u63d0\u793a\u6a21\u677f\u5bf9\u5176\u8fdb\u884c\u683c\u5f0f\u5316\uff0c\u7136\u540e\u5c06\u683c\u5f0f\u5316\u7684\u54cd\u5e94\u4f20\u9012\u7ed9LLM\u3002\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u5c06\u591a\u4e2a\u94fe\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u6216\u8005\u901a\u8fc7\u5c06\u94fe\u4e0e\u5176\u4ed6\u7ec4\u4ef6\u7ec4\u5408\u5728\u4e00\u8d77\u6765\u6784\u5efa\u66f4\u590d\u6742\u7684\u94fe\u3002"]}, {"cell_type": "markdown", "id": "21009bf6-49bd-466e-8177-74c23533d938", "metadata": {"tags": []}, "source": ["## \u4e00\u3001\u8bbe\u7f6eOpenAI API Key"]}, {"cell_type": "markdown", "id": "a2f5993b-f28d-4be4-984f-2d05be9f4579", "metadata": {}, "source": ["\u767b\u9646 [OpenAI \u8d26\u6237](https://platform.openai.com/account/api-keys) \u83b7\u53d6API Key\uff0c\u7136\u540e\u5c06\u5176\u8bbe\u7f6e\u4e3a\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u5168\u5c40\u73af\u5883\u53d8\u91cf\uff0c\u53ef\u4ee5\u53c2\u8003[\u77e5\u4e4e\u6587\u7ae0](https://zhuanlan.zhihu.com/p/627665725)\u3002\n", "- \u5982\u679c\u4f60\u60f3\u8981\u8bbe\u7f6e\u4e3a\u672c\u5730/\u9879\u76ee\u73af\u5883\u53d8\u91cf\uff0c\u5728\u672c\u6587\u4ef6\u76ee\u5f55\u4e0b\u521b\u5efa`.env`\u6587\u4ef6, \u6253\u5f00\u6587\u4ef6\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u3002\n", "\n", "

\n", " OPENAI_API_KEY=\"your_api_key\" \n", "

\n", " \n", " \u66ff\u6362\"your_api_key\"\u4e3a\u4f60\u81ea\u5df1\u7684 API Key"]}, {"cell_type": "code", "execution_count": 10, "id": "adc3519c-4d12-4011-9223-2f3cb3c42b93", "metadata": {}, "outputs": [], "source": ["# \u4e0b\u8f7d\u9700\u8981\u7684\u5305python-dotenv\u548copenai\n", "# \u5982\u679c\u4f60\u9700\u8981\u67e5\u770b\u5b89\u88c5\u8fc7\u7a0b\u65e5\u5fd7\uff0c\u53ef\u5220\u9664 -q \n", "!pip install -q python-dotenv\n", "!pip install -q openai"]}, {"cell_type": "code", "execution_count": 11, "id": "1ad53241-bef6-42b8-894b-bcbbc8c64df7", "metadata": {"tags": []}, "outputs": [], "source": ["import os\n", "import openai\n", "from dotenv import load_dotenv, find_dotenv\n", "\n", "# \u8bfb\u53d6\u672c\u5730/\u9879\u76ee\u7684\u73af\u5883\u53d8\u91cf\u3002\n", "\n", "# find_dotenv()\u5bfb\u627e\u5e76\u5b9a\u4f4d.env\u6587\u4ef6\u7684\u8def\u5f84\n", "# load_dotenv()\u8bfb\u53d6\u8be5.env\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u52a0\u8f7d\u5230\u5f53\u524d\u7684\u8fd0\u884c\u73af\u5883\u4e2d \n", "# \u5982\u679c\u4f60\u8bbe\u7f6e\u7684\u662f\u5168\u5c40\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u884c\u4ee3\u7801\u5219\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n", "_ = load_dotenv(find_dotenv())\n", "\n", "# \u83b7\u53d6\u73af\u5883\u53d8\u91cf OPENAI_API_KEY\n", "openai.api_key = os.environ['OPENAI_API_KEY'] "]}, {"cell_type": "markdown", "id": "b940ce7c", "metadata": {"tags": []}, "source": ["## \u4e8c\u3001\u5927\u8bed\u8a00\u6a21\u578b\u94fe"]}, {"cell_type": "markdown", "id": "e000bd16", "metadata": {}, "source": ["\u5927\u8bed\u8a00\u6a21\u578b\u94fe(LLMChain)\u662f\u4e00\u4e2a\u7b80\u5355\u4f46\u975e\u5e38\u5f3a\u5927\u7684\u94fe\uff0c\u4e5f\u662f\u540e\u9762\u6211\u4eec\u5c06\u8981\u4ecb\u7ecd\u7684\u8bb8\u591a\u94fe\u7684\u57fa\u7840\u3002"]}, {"cell_type": "markdown", "id": "d57e93b9-52ba-4f86-a953-e4661b895a3d", "metadata": {}, "source": ["### 2.1 \u5bfc\u5165\u6570\u636e"]}, {"cell_type": "code", "execution_count": 1, "id": "b84e441b", "metadata": {}, "outputs": [], "source": ["!pip install -q pandas"]}, {"cell_type": "code", "execution_count": 4, "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b", "metadata": {}, "outputs": [], "source": ["import pandas as pd\n", "df = pd.read_csv('data/Data.csv')"]}, {"cell_type": "code", "execution_count": 5, "id": "b7a09c35", "metadata": {}, "outputs": [{"data": {"text/html": ["
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ProductReview
0Queen Size Sheet SetI ordered a king size set. My only criticism w...
1Waterproof Phone PouchI loved the waterproof sac, although the openi...
2Luxury Air MattressThis mattress had a small hole in the top of i...
3Pillows InsertThis is the best throw pillow fillers on Amazo...
4Milk Frother Handheld\\nI loved this product. But they only seem to l...
\n", "
"], "text/plain": [" Product Review\n", "0 Queen Size Sheet Set I ordered a king size set. My only criticism w...\n", "1 Waterproof Phone Pouch I loved the waterproof sac, although the openi...\n", "2 Luxury Air Mattress This mattress had a small hole in the top of i...\n", "3 Pillows Insert This is the best throw pillow fillers on Amazo...\n", "4 Milk Frother Handheld\\n \u00a0I loved this product. But they only seem to l..."]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["df.head()"]}, {"cell_type": "markdown", "id": "daa83d10-04ee-4355-abe3-ab699c9eaca9", "metadata": {}, "source": ["### 2.2 \u521d\u59cb\u5316\u8bed\u8a00\u6a21\u578b"]}, {"cell_type": "code", "execution_count": 8, "id": "e92dff22", "metadata": {}, "outputs": [], "source": ["from langchain.chat_models import ChatOpenAI \n", "from langchain.prompts import ChatPromptTemplate \n", "from langchain.chains import LLMChain "]}, {"cell_type": "code", "execution_count": 13, "id": "943237a7", "metadata": {}, "outputs": [], "source": ["# \u8fd9\u91cc\u6211\u4eec\u5c06\u53c2\u6570temperature\u8bbe\u7f6e\u4e3a0.0\uff0c\u4ece\u800c\u51cf\u5c11\u751f\u6210\u7b54\u6848\u7684\u968f\u673a\u6027\u3002\n", "# \u5982\u679c\u4f60\u60f3\u8981\u6bcf\u6b21\u5f97\u5230\u4e0d\u4e00\u6837\u7684\u6709\u65b0\u610f\u7684\u7b54\u6848\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u8c03\u6574\u8be5\u53c2\u6570\u3002\n", "llm = ChatOpenAI(temperature=0.0) "]}, {"cell_type": "markdown", "id": "81887434", "metadata": {}, "source": ["### 2.3 \u521d\u59cb\u5316\u63d0\u793a\u6a21\u7248\n", "\u521d\u59cb\u5316\u63d0\u793a\uff0c\u8fd9\u4e2a\u63d0\u793a\u5c06\u63a5\u53d7\u4e00\u4e2a\u540d\u4e3aproduct\u7684\u53d8\u91cf\u3002\u8be5prompt\u5c06\u8981\u6c42LLM\u751f\u6210\u4e00\u4e2a\u63cf\u8ff0\u5236\u9020\u8be5\u4ea7\u54c1\u7684\u516c\u53f8\u7684\u6700\u4f73\u540d\u79f0"]}, {"cell_type": "code", "execution_count": 14, "id": "cdcdb42d", "metadata": {}, "outputs": [], "source": ["prompt = ChatPromptTemplate.from_template( \n", " \"What is the best name to describe \\\n", " a company that makes {product}?\"\n", ")"]}, {"cell_type": "markdown", "id": "5c22cb13", "metadata": {}, "source": ["### 2.4 \u6784\u5efa\u5927\u8bed\u8a00\u6a21\u578b\u94fe\n", "\n", "\u5c06\u5927\u8bed\u8a00\u6a21\u578b(LLM)\u548c\u63d0\u793a\uff08Prompt\uff09\u7ec4\u5408\u6210\u94fe\u3002\u8fd9\u4e2a\u5927\u8bed\u8a00\u6a21\u578b\u94fe\u975e\u5e38\u7b80\u5355\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u4ee5\u4e00\u79cd\u987a\u5e8f\u7684\u65b9\u5f0f\u53bb\u901a\u8fc7\u8fd0\u884c\u63d0\u793a\u5e76\u4e14\u7ed3\u5408\u5230\u5927\u8bed\u8a00\u6a21\u578b\u4e2d\u3002"]}, {"cell_type": "code", "execution_count": 15, "id": "d7abc20b", "metadata": {}, "outputs": [], "source": ["chain = LLMChain(llm=llm, prompt=prompt)"]}, {"cell_type": "markdown", "id": "8d7d5ff6", "metadata": {}, "source": ["### 2.5 \u8fd0\u884c\u5927\u8bed\u8a00\u6a21\u578b\u94fe\n", "\u56e0\u6b64\uff0c\u5982\u679c\u6211\u4eec\u6709\u4e00\u4e2a\u540d\u4e3a\"Queen Size Sheet Set\"\u7684\u4ea7\u54c1\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528chain.run\u5c06\u5176\u901a\u8fc7\u8fd9\u4e2a\u94fe\u8fd0\u884c"]}, {"cell_type": "code", "execution_count": 9, "id": "ad44d1fb", "metadata": {}, "outputs": [{"data": {"text/plain": ["'Royal Linens.'"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["product = \"Queen Size Sheet Set\"\n", "chain.run(product)"]}, {"cell_type": "markdown", "id": "1e1ede1c", "metadata": {}, "source": ["\u60a8\u53ef\u4ee5\u8f93\u5165\u4efb\u4f55\u4ea7\u54c1\u63cf\u8ff0\uff0c\u7136\u540e\u67e5\u770b\u94fe\u5c06\u8f93\u51fa\u4ec0\u4e48\u7ed3\u679c"]}, {"cell_type": "markdown", "id": "8ab31583-5cdf-4885-94d7-59c0d3b90b2e", "metadata": {}, "source": ["### 2.6 \u4e2d\u6587\u63d0\u793a"]}, {"cell_type": "code", "execution_count": 16, "id": "2181be10", "metadata": {}, "outputs": [{"data": {"text/plain": ["'\"\u8c6a\u534e\u5e8a\u7eba\"'"]}, "execution_count": 16, "metadata": {}, "output_type": "execute_result"}], "source": ["prompt = ChatPromptTemplate.from_template( \n", " \"\u63cf\u8ff0\u5236\u9020{product}\u7684\u4e00\u4e2a\u516c\u53f8\u7684\u6700\u4f73\u540d\u79f0\u662f\u4ec0\u4e48?\"\n", ")\n", "chain = LLMChain(llm=llm, prompt=prompt)\n", "product = \"\u5927\u53f7\u5e8a\u5355\u5957\u88c5\"\n", "chain.run(product)"]}, {"cell_type": "markdown", "id": "49158430", "metadata": {}, "source": ["## \u4e09\u3001\u987a\u5e8f\u94fe"]}, {"cell_type": "markdown", "id": "69b03469", "metadata": {}, "source": ["### 3.1 \u7b80\u5355\u987a\u5e8f\u94fe\n", "\n", "\u987a\u5e8f\u94fe\uff08SequentialChains\uff09\u662f\u6309\u9884\u5b9a\u4e49\u987a\u5e8f\u6267\u884c\u5176\u94fe\u63a5\u7684\u94fe\u3002\u5177\u4f53\u6765\u8bf4\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u7b80\u5355\u987a\u5e8f\u94fe\uff08SimpleSequentialChain\uff09\uff0c\u8fd9\u662f\u987a\u5e8f\u94fe\u7684\u6700\u7b80\u5355\u7c7b\u578b\uff0c\u5176\u4e2d\u6bcf\u4e2a\u6b65\u9aa4\u90fd\u6709\u4e00\u4e2a\u8f93\u5165/\u8f93\u51fa\uff0c\u4e00\u4e2a\u6b65\u9aa4\u7684\u8f93\u51fa\u662f\u4e0b\u4e00\u4e2a\u6b65\u9aa4\u7684\u8f93\u5165\u3002"]}, {"cell_type": "code", "execution_count": 28, "id": "febee243", "metadata": {}, "outputs": [], "source": ["from langchain.chains import SimpleSequentialChain"]}, {"cell_type": "code", "execution_count": 22, "id": "5d019d6f", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.9)"]}, {"cell_type": "markdown", "id": "0e732589", "metadata": {}, "source": ["#### 3.1.1 \u521b\u5efa\u4e24\u4e2a\u5b50\u94fe"]}, {"cell_type": "code", "execution_count": 23, "id": "2f31aa8a", "metadata": {}, "outputs": [], "source": ["# \u63d0\u793a\u6a21\u677f 1 \uff1a\u8fd9\u4e2a\u63d0\u793a\u5c06\u63a5\u53d7\u4ea7\u54c1\u5e76\u8fd4\u56de\u6700\u4f73\u540d\u79f0\u6765\u63cf\u8ff0\u8be5\u516c\u53f8\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"What is the best name to describe \\\n", " a company that makes {product}?\"\n", ")\n", "\n", "# Chain 1\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt)"]}, {"cell_type": "code", "execution_count": 24, "id": "3f5d5b76", "metadata": {}, "outputs": [], "source": ["\n", "# \u63d0\u793a\u6a21\u677f 2 \uff1a\u63a5\u53d7\u516c\u53f8\u540d\u79f0\uff0c\u7136\u540e\u8f93\u51fa\u8be5\u516c\u53f8\u7684\u957f\u4e3a20\u4e2a\u5355\u8bcd\u7684\u63cf\u8ff0\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"Write a 20 words description for the following \\\n", " company:{company_name}\"\n", ")\n", "# chain 2\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt)"]}, {"cell_type": "markdown", "id": "3a1991f4", "metadata": {}, "source": ["#### 3.1.2 \u6784\u5efa\u7b80\u5355\u987a\u5e8f\u94fe\n", "\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u7ec4\u5408\u4e24\u4e2aLLMChain\uff0c\u4ee5\u4fbf\u6211\u4eec\u53ef\u4ee5\u5728\u4e00\u4e2a\u6b65\u9aa4\u4e2d\u521b\u5efa\u516c\u53f8\u540d\u79f0\u548c\u63cf\u8ff0"]}, {"cell_type": "code", "execution_count": 25, "id": "6c1eb2c4", "metadata": {}, "outputs": [], "source": ["overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two], verbose=True)"]}, {"cell_type": "markdown", "id": "5122f26a", "metadata": {}, "source": ["\u7ed9\u4e00\u4e2a\u8f93\u5165\uff0c\u7136\u540e\u8fd0\u884c\u4e0a\u9762\u7684\u94fe"]}, {"cell_type": "markdown", "id": "9a80d102-da6b-49f4-8abd-7bff97211232", "metadata": {}, "source": ["#### 3.1.3 \u8fd0\u884c\u7b80\u5355\u987a\u5e8f\u94fe"]}, {"cell_type": "code", "execution_count": 27, "id": "78458efe", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "\u001b[36;1m\u001b[1;3mRoyal Rest Linens\u001b[0m\n", "\u001b[33;1m\u001b[1;3mRoyal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["\"Royal Rest Linens provides high-quality and luxurious linens for a comfortable and restful night's sleep.\""]}, "execution_count": 27, "metadata": {}, "output_type": "execute_result"}], "source": ["product = \"Queen Size Sheet Set\"\n", "overall_simple_chain.run(product)"]}, {"cell_type": "markdown", "id": "3983eb68-adf0-4c18-beed-ff6fc09cd78b", "metadata": {}, "source": ["#### 3.1.4 \u4e2d\u6587\u63d0\u793a"]}, {"cell_type": "code", "execution_count": 19, "id": "c7c32997", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", "\u001b[36;1m\u001b[1;3m\"\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\"\u001b[0m\n", "\u001b[33;1m\u001b[1;3m\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\u662f\u4e00\u5bb6\u4e13\u6ce8\u4e8e\u5e8a\u4e0a\u7528\u54c1\u751f\u4ea7\u7684\u516c\u53f8\u3002\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u5c3a\u5bf8\u738b\u5e8a\u54c1\u6709\u9650\u516c\u53f8\u662f\u4e00\u5bb6\u4e13\u6ce8\u4e8e\u5e8a\u4e0a\u7528\u54c1\u751f\u4ea7\u7684\u516c\u53f8\u3002'"]}, "execution_count": 19, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "\n", "first_prompt = ChatPromptTemplate.from_template( \n", " \"\u63cf\u8ff0\u5236\u9020{product}\u7684\u4e00\u4e2a\u516c\u53f8\u7684\u6700\u597d\u7684\u540d\u79f0\u662f\u4ec0\u4e48\"\n", ")\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt)\n", "\n", "second_prompt = ChatPromptTemplate.from_template( \n", " \"\u5199\u4e00\u4e2a20\u5b57\u7684\u63cf\u8ff0\u5bf9\u4e8e\u4e0b\u9762\u8fd9\u4e2a\\\n", " \u516c\u53f8\uff1a{company_name}\u7684\"\n", ")\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt)\n", "\n", "\n", "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],verbose=True)\n", "product = \"\u5927\u53f7\u5e8a\u5355\u5957\u88c5\"\n", "overall_simple_chain.run(product)"]}, {"cell_type": "markdown", "id": "7b5ce18c", "metadata": {}, "source": ["### 3.2 \u987a\u5e8f\u94fe"]}, {"cell_type": "markdown", "id": "1e69f4c0", "metadata": {}, "source": ["\u5f53\u53ea\u6709\u4e00\u4e2a\u8f93\u5165\u548c\u4e00\u4e2a\u8f93\u51fa\u65f6\uff0c\u7b80\u5355\u987a\u5e8f\u94fe\uff08SimpleSequentialChain\uff09\u5373\u53ef\u5b9e\u73b0\u3002\u5f53\u6709\u591a\u4e2a\u8f93\u5165\u6216\u591a\u4e2a\u8f93\u51fa\u65f6\uff0c\u6211\u4eec\u5219\u9700\u8981\u4f7f\u7528\u987a\u5e8f\u94fe\uff08SequentialChain\uff09\u6765\u5b9e\u73b0\u3002"]}, {"cell_type": "code", "execution_count": 29, "id": "4c129ef6", "metadata": {}, "outputs": [], "source": ["from langchain.chains import SequentialChain\n", "from langchain.chat_models import ChatOpenAI #\u5bfc\u5165OpenAI\u6a21\u578b\n", "from langchain.prompts import ChatPromptTemplate #\u5bfc\u5165\u804a\u5929\u63d0\u793a\u6a21\u677f\n", "from langchain.chains import LLMChain #\u5bfc\u5165LLM\u94fe\u3002"]}, {"cell_type": "code", "execution_count": 30, "id": "03a8e203", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0.9)"]}, {"cell_type": "markdown", "id": "9811445c", "metadata": {}, "source": ["\u63a5\u4e0b\u6765\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u7cfb\u5217\u7684\u94fe\uff0c\u7136\u540e\u4e00\u4e2a\u63a5\u4e00\u4e2a\u4f7f\u7528\u4ed6\u4eec"]}, {"cell_type": "markdown", "id": "df9e87ec-b99a-4130-a5b5-cdce064dc6ca", "metadata": {}, "source": ["#### 3.2.1 \u521b\u5efa\u56db\u4e2a\u5b50\u94fe"]}, {"cell_type": "code", "execution_count": 38, "id": "016187ac", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe1\n", "\n", "# prompt\u6a21\u677f 1: \u7ffb\u8bd1\u6210\u82f1\u8bed\uff08\u628a\u4e0b\u9762\u7684review\u7ffb\u8bd1\u6210\u82f1\u8bed\uff09\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"Translate the following review to english:\"\n", " \"\\n\\n{Review}\"\n", ")\n", "# chain 1: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a \u82f1\u6587\u7684 Review\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")"]}, {"cell_type": "code", "execution_count": 39, "id": "0fb0730e", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe2\n", "\n", "# prompt\u6a21\u677f 2: \u7528\u4e00\u53e5\u8bdd\u603b\u7ed3\u4e0b\u9762\u7684 review\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"Can you summarize the following review in 1 sentence:\"\n", " \"\\n\\n{English_Review}\"\n", ")\n", "# chain 2: \u8f93\u5165\uff1a\u82f1\u6587\u7684Review \u8f93\u51fa\uff1a\u603b\u7ed3\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n"]}, {"cell_type": "code", "execution_count": 40, "id": "6accf92d", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe3\n", "\n", "# prompt\u6a21\u677f 3: \u4e0b\u9762review\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00\n", "third_prompt = ChatPromptTemplate.from_template(\n", " \"What language is the following review:\\n\\n{Review}\"\n", ")\n", "# chain 3: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u8bed\u8a00\n", "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n"]}, {"cell_type": "code", "execution_count": 41, "id": "c7a46121", "metadata": {}, "outputs": [], "source": ["#\u5b50\u94fe4\n", "\n", "# prompt\u6a21\u677f 4: \u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d\n", "fourth_prompt = ChatPromptTemplate.from_template(\n", " \"Write a follow up response to the following \"\n", " \"summary in the specified language:\"\n", " \"\\n\\nSummary: {summary}\\n\\nLanguage: {language}\"\n", ")\n", "# chain 4: \u8f93\u5165\uff1a \u603b\u7ed3, \u8bed\u8a00 \u8f93\u51fa\uff1a \u540e\u7eed\u56de\u590d\n", "chain_four = LLMChain(llm=llm, prompt=fourth_prompt, output_key=\"followup_message\")\n"]}, {"cell_type": "markdown", "id": "ff435291-5d20-4c3e-9ed7-76a1140f96d2", "metadata": {}, "source": ["#### 3.2.2 \u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408"]}, {"cell_type": "code", "execution_count": 42, "id": "89603117", "metadata": {}, "outputs": [], "source": ["#\u8f93\u5165\uff1areview \n", "#\u8f93\u51fa\uff1a\u82f1\u6587review\uff0c\u603b\u7ed3\uff0c\u540e\u7eed\u56de\u590d \n", "overall_chain = SequentialChain(\n", " chains=[chain_one, chain_two, chain_three, chain_four],\n", " input_variables=[\"Review\"],\n", " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", " verbose=True\n", ")"]}, {"cell_type": "markdown", "id": "0509de01", "metadata": {}, "source": ["\u8ba9\u6211\u4eec\u9009\u62e9\u4e00\u7bc7\u8bc4\u8bba\u5e76\u901a\u8fc7\u6574\u4e2a\u94fe\u4f20\u9012\u5b83\uff0c\u53ef\u4ee5\u53d1\u73b0\uff0c\u539f\u59cbreview\u662f\u6cd5\u8bed\uff0c\u53ef\u4ee5\u628a\u82f1\u6587review\u770b\u505a\u662f\u4e00\u79cd\u7ffb\u8bd1\uff0c\u63a5\u4e0b\u6765\u662f\u6839\u636e\u82f1\u6587review\u5f97\u5230\u7684\u603b\u7ed3\uff0c\u6700\u540e\u8f93\u51fa\u7684\u662f\u7528\u6cd5\u8bed\u539f\u6587\u8fdb\u884c\u7684\u7eed\u5199\u4fe1\u606f\u3002"]}, {"cell_type": "code", "execution_count": 43, "id": "51b04f45", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["{'Review': \"Je trouve le go\u00fbt m\u00e9diocre. La mousse ne tient pas, c'est bizarre. J'ach\u00e8te les m\u00eames dans le commerce et le go\u00fbt est bien meilleur...\\nVieux lot ou contrefa\u00e7on !?\",\n", " 'English_Review': \"I find the taste mediocre. The foam doesn't hold, it's weird. I buy the same ones in the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", " 'summary': 'The reviewer is disappointed with the taste and consistency of the product, suspecting that either an old batch or counterfeit version is the cause.',\n", " 'followup_message': \"R\u00e9ponse de suivi :\\n\\nCher(e) critique,\\n\\nNous sommes d\u00e9sol\u00e9s d'apprendre que notre produit ne r\u00e9pond pas \u00e0 vos attentes. Nous prenons tr\u00e8s au s\u00e9rieux les commentaires de nos clients et nous tenons \u00e0 vous rassurer que nous attachons une grande importance \u00e0 la qualit\u00e9 de nos produits.\\n\\nNous v\u00e9rifions constamment nos processus de production afin de nous assurer que nos produits sont toujours frais et authentiques. Si vous pensez avoir re\u00e7u un produit contrefait ou un lot p\u00e9rim\u00e9, nous vous prions de nous contacter directement afin de r\u00e9soudre ce probl\u00e8me au plus vite. Nous avons un service client d\u00e9di\u00e9 qui sera ravi de vous aider avec votre pr\u00e9occupation.\\n\\nNous tenons \u00e0 nous excuser pour toute d\u00e9ception ou d\u00e9sagr\u00e9ment que cela aurait pu causer. Votre satisfaction est notre priorit\u00e9 absolue et nous ferons tout notre possible pour rem\u00e9dier \u00e0 la situation et regagner votre confiance.\\n\\nNous vous remercions de votre compr\u00e9hension et de votre patience. Votre avis est important pour nous et nous esp\u00e9rons avoir l'occasion de nous rattraper \u00e0 l'avenir.\\n\\nCordialement,\\nL'\u00e9quipe de [Nom de l'entreprise]\"}"]}, "execution_count": 43, "metadata": {}, "output_type": "execute_result"}], "source": ["review = df.Review[5]\n", "overall_chain(review)"]}, {"cell_type": "markdown", "id": "18d72f1d-8a1e-4eb6-b00f-1963b3cf3adb", "metadata": {}, "source": ["#### 3.2.3 \u4e2d\u6587\u63d0\u793a"]}, {"cell_type": "code", "execution_count": 37, "id": "31624a7c", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new chain...\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["{'Review': \"Je trouve le go\u00fbt m\u00e9diocre. La mousse ne tient pas, c'est bizarre. J'ach\u00e8te les m\u00eames dans le commerce et le go\u00fbt est bien meilleur...\\nVieux lot ou contrefa\u00e7on !?\",\n", " 'English_Review': \"I find the taste mediocre. The foam doesn't last, it's weird. I buy the same ones from the store and the taste is much better...\\nOld batch or counterfeit!?\",\n", " 'summary': \"The taste is mediocre, the foam doesn't last, and there is suspicion of old batch or counterfeit.\",\n", " 'followup_message': \"\u56de\u590d: Je suis d\u00e9sol\u00e9 de vous entendre dire que le go\u00fbt est moyen et que la mousse ne dure pas longtemps. Nous prenons ces probl\u00e8mes tr\u00e8s au s\u00e9rieux. Nous allons enqu\u00eater pour v\u00e9rifier s'il s'agit d'un ancien lot ou d'une contrefa\u00e7on. Votre satisfaction est notre priorit\u00e9 et nous ferons de notre mieux pour r\u00e9soudre ce probl\u00e8me. Merci de nous avoir inform\u00e9s.\"}"]}, "execution_count": 37, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "\n", "#\u5b50\u94fe1\n", "# prompt\u6a21\u677f 1: \u7ffb\u8bd1\u6210\u82f1\u8bed\uff08\u628a\u4e0b\u9762\u7684review\u7ffb\u8bd1\u6210\u82f1\u8bed\uff09\n", "first_prompt = ChatPromptTemplate.from_template(\n", " \"\u628a\u4e0b\u9762\u7684\u8bc4\u8bbareview\u7ffb\u8bd1\u6210\u82f1\u6587:\"\n", " \"\\n\\n{Review}\"\n", ")\n", "# chain 1: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u82f1\u6587\u7684 Review\n", "chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key=\"English_Review\")\n", "\n", "#\u5b50\u94fe2\n", "# prompt\u6a21\u677f 2: \u7528\u4e00\u53e5\u8bdd\u603b\u7ed3\u4e0b\u9762\u7684 review\n", "second_prompt = ChatPromptTemplate.from_template(\n", " \"\u8bf7\u4f60\u7528\u4e00\u53e5\u8bdd\u6765\u603b\u7ed3\u4e0b\u9762\u7684\u8bc4\u8bbareview:\"\n", " \"\\n\\n{English_Review}\"\n", ")\n", "# chain 2: \u8f93\u5165\uff1a\u82f1\u6587\u7684Review \u8f93\u51fa\uff1a\u603b\u7ed3\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key=\"summary\")\n", "\n", "\n", "#\u5b50\u94fe3\n", "# prompt\u6a21\u677f 3: \u4e0b\u9762review\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00\n", "third_prompt = ChatPromptTemplate.from_template(\n", " \"\u4e0b\u9762\u7684\u8bc4\u8bbareview\u4f7f\u7528\u7684\u4ec0\u4e48\u8bed\u8a00:\\n\\n{Review}\"\n", ")\n", "# chain 3: \u8f93\u5165\uff1aReview \u8f93\u51fa\uff1a\u8bed\u8a00\n", "chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key=\"language\")\n", "\n", "\n", "#\u5b50\u94fe4\n", "# prompt\u6a21\u677f 4: \u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d\n", "fourth_prompt = ChatPromptTemplate.from_template(\n", " \"\u4f7f\u7528\u7279\u5b9a\u7684\u8bed\u8a00\u5bf9\u4e0b\u9762\u7684\u603b\u7ed3\u5199\u4e00\u4e2a\u540e\u7eed\u56de\u590d:\"\n", " \"\\n\\n\u603b\u7ed3: {summary}\\n\\n\u8bed\u8a00: {language}\"\n", ")\n", "# chain 4: \u8f93\u5165\uff1a \u603b\u7ed3, \u8bed\u8a00 \u8f93\u51fa\uff1a \u540e\u7eed\u56de\u590d\n", "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n", " output_key=\"followup_message\"\n", " )\n", "\n", "\n", "# \u5bf9\u56db\u4e2a\u5b50\u94fe\u8fdb\u884c\u7ec4\u5408\n", "#\u8f93\u5165\uff1areview \u8f93\u51fa\uff1a\u82f1\u6587review\uff0c\u603b\u7ed3\uff0c\u540e\u7eed\u56de\u590d \n", "overall_chain = SequentialChain(\n", " chains=[chain_one, chain_two, chain_three, chain_four],\n", " input_variables=[\"Review\"],\n", " output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n", " verbose=True\n", ")\n", "\n", "\n", "review = df.Review[5]\n", "overall_chain(review)"]}, {"cell_type": "markdown", "id": "3041ea4c", "metadata": {}, "source": ["## \u56db\u3001 \u8def\u7531\u94fe"]}, {"cell_type": "markdown", "id": "f0c32f97", "metadata": {}, "source": ["\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5df2\u7ecf\u5b66\u4e60\u4e86\u5927\u8bed\u8a00\u6a21\u578b\u94fe\u548c\u987a\u5e8f\u94fe\u3002\u4f46\u662f\uff0c\u5982\u679c\u6211\u4eec\u60f3\u505a\u4e00\u4e9b\u66f4\u590d\u6742\u7684\u4e8b\u60c5\u600e\u4e48\u529e\uff1f\n", "\n", "\u4e00\u4e2a\u76f8\u5f53\u5e38\u89c1\u4f46\u57fa\u672c\u7684\u64cd\u4f5c\u662f\u6839\u636e\u8f93\u5165\u5c06\u5176\u8def\u7531\u5230\u4e00\u6761\u94fe\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u8be5\u8f93\u5165\u5230\u5e95\u662f\u4ec0\u4e48\u3002\u5982\u679c\u4f60\u6709\u591a\u4e2a\u5b50\u94fe\uff0c\u6bcf\u4e2a\u5b50\u94fe\u90fd\u4e13\u95e8\u7528\u4e8e\u7279\u5b9a\u7c7b\u578b\u7684\u8f93\u5165\uff0c\u90a3\u4e48\u53ef\u4ee5\u7ec4\u6210\u4e00\u4e2a\u8def\u7531\u94fe\uff0c\u5b83\u9996\u5148\u51b3\u5b9a\u5c06\u5b83\u4f20\u9012\u7ed9\u54ea\u4e2a\u5b50\u94fe\uff0c\u7136\u540e\u5c06\u5b83\u4f20\u9012\u7ed9\u90a3\u4e2a\u94fe\u3002\n", "\n", "\u8def\u7531\u5668\u7531\u4e24\u4e2a\u7ec4\u4ef6\u7ec4\u6210\uff1a\n", "\n", "- \u8def\u7531\u94fe\uff08Router Chain\uff09\uff1a\u8def\u7531\u5668\u94fe\u672c\u8eab\uff0c\u8d1f\u8d23\u9009\u62e9\u8981\u8c03\u7528\u7684\u4e0b\u4e00\u4e2a\u94fe\n", "- destination_chains\uff1a\u8def\u7531\u5668\u94fe\u53ef\u4ee5\u8def\u7531\u5230\u7684\u94fe\n", "\n", "\u4e3e\u4e00\u4e2a\u5177\u4f53\u7684\u4f8b\u5b50\uff0c\u8ba9\u6211\u4eec\u770b\u4e00\u4e0b\u6211\u4eec\u5728\u4e0d\u540c\u7c7b\u578b\u7684\u94fe\u4e4b\u95f4\u8def\u7531\u7684\u5730\u65b9\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u6709\u4e0d\u540c\u7684prompt: "]}, {"cell_type": "code", "execution_count": 28, "id": "31b06fc8", "metadata": {}, "outputs": [], "source": ["from langchain.chains.router import MultiPromptChain #\u5bfc\u5165\u591a\u63d0\u793a\u94fe\n", "from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser\n", "from langchain.prompts import PromptTemplate"]}, {"cell_type": "code", "execution_count": 29, "id": "f3f50bcc", "metadata": {}, "outputs": [], "source": ["llm = ChatOpenAI(temperature=0)"]}, {"cell_type": "markdown", "id": "cb1b4708", "metadata": {}, "source": ["### 4.1 \u5b9a\u4e49\u63d0\u793a\u6a21\u677f"]}, {"cell_type": "markdown", "id": "c3b85285-c736-4a5d-bd14-d9b5025ca29b", "metadata": {}, "source": ["\u9996\u5148\uff0c\u6211\u4eec\u5b9a\u4e49\u63d0\u793a\u9002\u7528\u4e8e\u4e0d\u540c\u573a\u666f\u4e0b\u7684\u63d0\u793a\u6a21\u677f\u3002"]}, {"cell_type": "code", "execution_count": 49, "id": "ade83f4f", "metadata": {}, "outputs": [], "source": ["#\u7b2c\u4e00\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u7269\u7406\u95ee\u9898\n", "physics_template = \"\"\"You are a very smart physics professor. \\\n", "You are great at answering questions about physics in a concise\\\n", "and easy to understand manner. \\\n", "When you don't know the answer to a question you admit\\\n", "that you don't know.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e8c\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u6570\u5b66\u95ee\u9898\n", "math_template = \"\"\"You are a very good mathematician. \\\n", "You are great at answering math questions. \\\n", "You are so good because you are able to break down \\\n", "hard problems into their component parts, \n", "answer the component parts, and then put them together\\\n", "to answer the broader question.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e09\u4e2a\u9002\u5408\u56de\u7b54\u5386\u53f2\u95ee\u9898\n", "history_template = \"\"\"You are a very good historian. \\\n", "You have an excellent knowledge of and understanding of people,\\\n", "events and contexts from a range of historical periods. \\\n", "You have the ability to think, reflect, debate, discuss and \\\n", "evaluate the past. You have a respect for historical evidence\\\n", "and the ability to make use of it to support your explanations \\\n", "and judgements.\n", "\n", "Here is a question:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u56db\u4e2a\u9002\u5408\u56de\u7b54\u8ba1\u7b97\u673a\u95ee\u9898\n", "computerscience_template = \"\"\" You are a successful computer scientist.\\\n", "You have a passion for creativity, collaboration,\\\n", "forward-thinking, confidence, strong problem-solving capabilities,\\\n", "understanding of theories and algorithms, and excellent communication \\\n", "skills. You are great at answering coding questions. \\\n", "You are so good because you know how to solve a problem by \\\n", "describing the solution in imperative steps \\\n", "that a machine can easily interpret and you know how to \\\n", "choose a solution that has a good balance between \\\n", "time complexity and space complexity. \n", "\n", "Here is a question:\n", "{input}\"\"\""]}, {"cell_type": "markdown", "id": "cb3b749b-0d3c-46f2-afab-b1213f208b13", "metadata": {}, "source": ["### 4.2 \u5bf9\u63d0\u793a\u6a21\u7248\u8fdb\u884c\u547d\u540d\u548c\u63cf\u8ff0"]}, {"cell_type": "markdown", "id": "6922b35e", "metadata": {}, "source": ["\u5728\u5b9a\u4e49\u4e86\u8fd9\u4e9b\u63d0\u793a\u6a21\u677f\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u4e3a\u6bcf\u4e2a\u6a21\u677f\u547d\u540d\uff0c\u5e76\u7ed9\u51fa\u5177\u4f53\u63cf\u8ff0\u3002\u4f8b\u5982\uff0c\u7b2c\u4e00\u4e2a\u7269\u7406\u5b66\u7684\u63cf\u8ff0\u9002\u5408\u56de\u7b54\u5173\u4e8e\u7269\u7406\u5b66\u7684\u95ee\u9898\uff0c\u8fd9\u4e9b\u4fe1\u606f\u5c06\u4f20\u9012\u7ed9\u8def\u7531\u94fe\uff0c\u7136\u540e\u7531\u8def\u7531\u94fe\u51b3\u5b9a\u4f55\u65f6\u4f7f\u7528\u6b64\u5b50\u94fe\u3002"]}, {"cell_type": "code", "execution_count": 27, "id": "141a3d32", "metadata": {}, "outputs": [], "source": ["prompt_infos = [\n", " {\n", " \"name\": \"physics\", \n", " \"description\": \"Good for answering questions about physics\", \n", " \"prompt_template\": physics_template\n", " },\n", " {\n", " \"name\": \"math\", \n", " \"description\": \"Good for answering math questions\", \n", " \"prompt_template\": math_template\n", " },\n", " {\n", " \"name\": \"History\", \n", " \"description\": \"Good for answering history questions\", \n", " \"prompt_template\": history_template\n", " },\n", " {\n", " \"name\": \"computer science\", \n", " \"description\": \"Good for answering computer science questions\", \n", " \"prompt_template\": computerscience_template\n", " }\n", "]"]}, {"cell_type": "markdown", "id": "8795cd42", "metadata": {}, "source": ["LLMRouterChain\uff08\u6b64\u94fe\u4f7f\u7528 LLM \u6765\u786e\u5b9a\u5982\u4f55\u8def\u7531\u4e8b\u7269\uff09\n", "\n", "\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u9700\u8981\u4e00\u4e2a**\u591a\u63d0\u793a\u94fe**\u3002\u8fd9\u662f\u4e00\u79cd\u7279\u5b9a\u7c7b\u578b\u7684\u94fe\uff0c\u7528\u4e8e\u5728\u591a\u4e2a\u4e0d\u540c\u7684\u63d0\u793a\u6a21\u677f\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002 \u4f46\u662f\u8fd9\u53ea\u662f\u8def\u7531\u7684\u4e00\u79cd\u7c7b\u578b\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u5728\u4efb\u4f55\u7c7b\u578b\u7684\u94fe\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002\n", "\n", "\u8fd9\u91cc\u6211\u4eec\u8981\u5b9e\u73b0\u7684\u51e0\u4e2a\u7c7b\u662f\u5927\u6a21\u578b\u8def\u7531\u5668\u94fe\u3002\u8fd9\u4e2a\u7c7b\u672c\u8eab\u4f7f\u7528\u8bed\u8a00\u6a21\u578b\u6765\u5728\u4e0d\u540c\u7684\u5b50\u94fe\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002\u8fd9\u5c31\u662f\u4e0a\u9762\u63d0\u4f9b\u7684\u63cf\u8ff0\u548c\u540d\u79f0\u5c06\u88ab\u4f7f\u7528\u7684\u5730\u65b9\u3002"]}, {"cell_type": "markdown", "id": "46633b43", "metadata": {}, "source": ["### 4.3 \u57fa\u4e8e\u63d0\u793a\u6a21\u7248\u4fe1\u606f\u521b\u5efa\u76f8\u5e94\u76ee\u6807\u94fe \n", "\u76ee\u6807\u94fe\u662f\u7531\u8def\u7531\u94fe\u8c03\u7528\u7684\u94fe\uff0c\u6bcf\u4e2a\u76ee\u6807\u94fe\u90fd\u662f\u4e00\u4e2a\u8bed\u8a00\u6a21\u578b\u94fe"]}, {"cell_type": "code", "execution_count": 30, "id": "8eefec24", "metadata": {}, "outputs": [], "source": ["destination_chains = {}\n", "for p_info in prompt_infos:\n", " name = p_info[\"name\"]\n", " prompt_template = p_info[\"prompt_template\"]\n", " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", " chain = LLMChain(llm=llm, prompt=prompt)\n", " destination_chains[name] = chain \n", " \n", "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n", "destinations_str = \"\\n\".join(destinations)"]}, {"cell_type": "markdown", "id": "eba115de", "metadata": {"tags": []}, "source": ["### 4.4 \u521b\u5efa\u9ed8\u8ba4\u76ee\u6807\u94fe\n", "\u9664\u4e86\u76ee\u6807\u94fe\u4e4b\u5916\uff0c\u6211\u4eec\u8fd8\u9700\u8981\u4e00\u4e2a\u9ed8\u8ba4\u76ee\u6807\u94fe\u3002\u8fd9\u662f\u4e00\u4e2a\u5f53\u8def\u7531\u5668\u65e0\u6cd5\u51b3\u5b9a\u4f7f\u7528\u54ea\u4e2a\u5b50\u94fe\u65f6\u8c03\u7528\u7684\u94fe\u3002\u5728\u4e0a\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u5f53\u8f93\u5165\u95ee\u9898\u4e0e\u7269\u7406\u3001\u6570\u5b66\u3001\u5386\u53f2\u6216\u8ba1\u7b97\u673a\u79d1\u5b66\u65e0\u5173\u65f6\uff0c\u53ef\u80fd\u4f1a\u8c03\u7528\u5b83\u3002"]}, {"cell_type": "code", "execution_count": 31, "id": "9f98018a", "metadata": {}, "outputs": [], "source": ["default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", "default_chain = LLMChain(llm=llm, prompt=default_prompt)"]}, {"cell_type": "markdown", "id": "948700c4", "metadata": {}, "source": ["### 4.5 \u5b9a\u4e49\u4e0d\u540c\u94fe\u4e4b\u95f4\u7684\u8def\u7531\u6a21\u677f\n", "\n", "\u8fd9\u5305\u62ec\u8981\u5b8c\u6210\u7684\u4efb\u52a1\u7684\u8bf4\u660e\u4ee5\u53ca\u8f93\u51fa\u5e94\u8be5\u91c7\u7528\u7684\u7279\u5b9a\u683c\u5f0f\u3002"]}, {"cell_type": "markdown", "id": "24f30c2c", "metadata": {}, "source": ["\u6ce8\u610f\uff1a\u6b64\u5904\u5728\u539f\u6559\u7a0b\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u4e00\u4e2a\u793a\u4f8b\uff0c\u4e3b\u8981\u662f\u56e0\u4e3a\"gpt-3.5-turbo\"\u6a21\u578b\u4e0d\u80fd\u5f88\u597d\u9002\u5e94\u7406\u89e3\u6a21\u677f\u7684\u610f\u601d\uff0c\u4f7f\u7528 \"text-davinci-003\" \u6216\u8005\"gpt-4-0613\"\u53ef\u4ee5\u5f88\u597d\u7684\u5de5\u4f5c\uff0c\u56e0\u6b64\u5728\u8fd9\u91cc\u591a\u52a0\u4e86\u793a\u4f8b\u63d0\u793a\u8ba9\u5176\u66f4\u597d\u7684\u5b66\u4e60\u3002\n", "eg:\n", "<< INPUT >>\n", "\"What is black body radiation?\"\n", "<< OUTPUT >>\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```"]}, {"cell_type": "code", "execution_count": 32, "id": "11b2e2ba", "metadata": {}, "outputs": [], "source": ["MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"Given a raw text input to a \\\n", "language model select the model prompt best suited for the input. \\\n", "You will be given the names of the available prompts and a \\\n", "description of what the prompt is best suited for. \\\n", "You may also revise the original input if you think that revising\\\n", "it will ultimately lead to a better response from the language model.\n", "\n", "<< FORMATTING >>\n", "Return a markdown code snippet with a JSON object formatted to look like:\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```\n", "\n", "REMEMBER: \"destination\" MUST be one of the candidate prompt \\\n", "names specified below OR it can be \"DEFAULT\" if the input is not\\\n", "well suited for any of the candidate prompts.\n", "REMEMBER: \"next_inputs\" can just be the original input \\\n", "if you don't think any modifications are needed.\n", "\n", "<< CANDIDATE PROMPTS >>\n", "{destinations}\n", "\n", "<< INPUT >>\n", "{{input}}\n", "\n", "<< OUTPUT (remember to include the ```json)>>\n", "\n", "eg:\n", "<< INPUT >>\n", "\"What is black body radiation?\"\n", "<< OUTPUT >>\n", "```json\n", "{{{{\n", " \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n", " \"next_inputs\": string \\ a potentially modified version of the original input\n", "}}}}\n", "```\n", "\n", "\"\"\""]}, {"cell_type": "markdown", "id": "de5c46d0", "metadata": {}, "source": ["### 4.6 \u6784\u5efa\u8def\u7531\u94fe\n", "\u9996\u5148\uff0c\u6211\u4eec\u901a\u8fc7\u683c\u5f0f\u5316\u4e0a\u9762\u5b9a\u4e49\u7684\u76ee\u6807\u521b\u5efa\u5b8c\u6574\u7684\u8def\u7531\u5668\u6a21\u677f\u3002\u8fd9\u4e2a\u6a21\u677f\u53ef\u4ee5\u9002\u7528\u8bb8\u591a\u4e0d\u540c\u7c7b\u578b\u7684\u76ee\u6807\u3002\n", "\u56e0\u6b64\uff0c\u5728\u8fd9\u91cc\uff0c\u60a8\u53ef\u4ee5\u6dfb\u52a0\u4e00\u4e2a\u4e0d\u540c\u7684\u5b66\u79d1\uff0c\u5982\u82f1\u8bed\u6216\u62c9\u4e01\u8bed\uff0c\u800c\u4e0d\u4ec5\u4ec5\u662f\u7269\u7406\u3001\u6570\u5b66\u3001\u5386\u53f2\u548c\u8ba1\u7b97\u673a\u79d1\u5b66\u3002\n", "\n", "\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u4ece\u8fd9\u4e2a\u6a21\u677f\u521b\u5efa\u63d0\u793a\u6a21\u677f\n", "\n", "\u6700\u540e\uff0c\u901a\u8fc7\u4f20\u5165llm\u548c\u6574\u4e2a\u8def\u7531\u63d0\u793a\u6765\u521b\u5efa\u8def\u7531\u94fe\u3002\u9700\u8981\u6ce8\u610f\u7684\u662f\u8fd9\u91cc\u6709\u8def\u7531\u8f93\u51fa\u89e3\u6790\uff0c\u8fd9\u5f88\u91cd\u8981\uff0c\u56e0\u4e3a\u5b83\u5c06\u5e2e\u52a9\u8fd9\u4e2a\u94fe\u8def\u51b3\u5b9a\u5728\u54ea\u4e9b\u5b50\u94fe\u8def\u4e4b\u95f4\u8fdb\u884c\u8def\u7531\u3002"]}, {"cell_type": "code", "execution_count": 34, "id": "1387109d", "metadata": {}, "outputs": [], "source": ["router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(\n", " destinations=destinations_str\n", ")\n", "router_prompt = PromptTemplate(\n", " template=router_template,\n", " input_variables=[\"input\"],\n", " output_parser=RouterOutputParser(),\n", ")\n", "\n", "router_chain = LLMRouterChain.from_llm(llm, router_prompt)"]}, {"cell_type": "markdown", "id": "7e92355c", "metadata": {}, "source": ["### 4.7 \u521b\u5efa\u6574\u4f53\u94fe\u8def"]}, {"cell_type": "code", "execution_count": 35, "id": "2fb7d560", "metadata": {}, "outputs": [], "source": ["#\u591a\u63d0\u793a\u94fe\n", "chain = MultiPromptChain(router_chain=router_chain, #l\u8def\u7531\u94fe\u8def\n", " destination_chains=destination_chains, #\u76ee\u6807\u94fe\u8def\n", " default_chain=default_chain, #\u9ed8\u8ba4\u94fe\u8def\n", " verbose=True \n", " )"]}, {"cell_type": "markdown", "id": "086503f7", "metadata": {}, "source": ["### 4.8 \u8fdb\u884c\u63d0\u95ee"]}, {"cell_type": "markdown", "id": "969cd878", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u95ee\u4e00\u4e2a\u7269\u7406\u95ee\u9898\uff0c\u6211\u4eec\u5e0c\u671b\u770b\u5230\u4ed6\u88ab\u8def\u7531\u5230\u7269\u7406\u94fe\u8def"]}, {"cell_type": "code", "execution_count": null, "id": "2217d987", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "physics: {'input': 'What is black body radiation?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Black body radiation is the electromagnetic radiation emitted by a perfect black body, which absorbs all incident radiation and reflects none. It is characterized by a continuous spectrum of radiated energy that is dependent on the temperature of the body, with higher temperatures leading to more intense and shorter wavelength radiation. This phenomenon is an important concept in thermal physics and has numerous applications, ranging from understanding stellar spectra to designing artificial light sources.'"]}, "metadata": {}, "output_type": "display_data"}], "source": ["# \u95ee\u9898\uff1a\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f\n", "chain.run(\"What is black body radiation?\")"]}, {"cell_type": "markdown", "id": "289c5ca9", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u95ee\u4e00\u4e2a\u6570\u5b66\u95ee\u9898\uff0c\u6211\u4eec\u5e0c\u671b\u770b\u5230\u4ed6\u88ab\u8def\u7531\u5230\u6570\u5b66\u94fe\u8def"]}, {"cell_type": "code", "execution_count": 22, "id": "3b717379", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "math: {'input': 'what is 2 + 2'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'As an AI language model, I can answer this question. The answer to 2 + 2 is 4.'"]}, "execution_count": 22, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u95ee\u9898\uff1a2+2\u7b49\u4e8e\u591a\u5c11\uff1f\n", "chain.run(\"what is 2 + 2\")"]}, {"cell_type": "markdown", "id": "4186a2b9", "metadata": {}, "source": ["\u5982\u679c\u6211\u4eec\u4f20\u9012\u4e00\u4e2a\u4e0e\u4efb\u4f55\u5b50\u94fe\u8def\u90fd\u65e0\u5173\u7684\u95ee\u9898\u65f6\uff0c\u4f1a\u53d1\u751f\u4ec0\u4e48\u5462\uff1f\n", "\n", "\u8fd9\u91cc\uff0c\u6211\u4eec\u95ee\u4e86\u4e00\u4e2a\u5173\u4e8e\u751f\u7269\u5b66\u7684\u95ee\u9898\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u5b83\u9009\u62e9\u7684\u94fe\u8def\u662f\u65e0\u3002\u8fd9\u610f\u5473\u7740\u5b83\u5c06\u88ab**\u4f20\u9012\u5230\u9ed8\u8ba4\u94fe\u8def\uff0c\u5b83\u672c\u8eab\u53ea\u662f\u5bf9\u8bed\u8a00\u6a21\u578b\u7684\u901a\u7528\u8c03\u7528**\u3002\u8bed\u8a00\u6a21\u578b\u5e78\u8fd0\u5730\u5bf9\u751f\u7269\u5b66\u77e5\u9053\u5f88\u591a\uff0c\u6240\u4ee5\u5b83\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u3002"]}, {"cell_type": "code", "execution_count": 40, "id": "29e5be01", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "None: {'input': 'Why does every cell in our body contain DNA?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'Every cell in our body contains DNA because DNA carries the genetic information that determines the characteristics and functions of each cell. DNA contains the instructions for the synthesis of proteins, which are essential for the structure and function of cells. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next. Therefore, every cell in our body needs DNA to carry out its specific functions and to maintain the integrity of the organism as a whole.'"]}, "execution_count": 40, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u95ee\u9898\uff1a\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f\n", "chain.run(\"Why does every cell in our body contain DNA?\")"]}, {"cell_type": "markdown", "id": "753b5f1d-b010-4f33-a928-d3b9e85bf289", "metadata": {}, "source": ["### 4.9 \u4e2d\u6587\u63d0\u793a"]}, {"cell_type": "code", "execution_count": 51, "id": "f7fade7a", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "#\u7b2c\u4e00\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u7269\u7406\u95ee\u9898\n", "physics_template = \"\"\"\u4f60\u662f\u4e00\u4e2a\u975e\u5e38\u806a\u660e\u7684\u7269\u7406\u4e13\u5bb6\u3002 \\\n", "\u4f60\u64c5\u957f\u7528\u4e00\u79cd\u7b80\u6d01\u5e76\u4e14\u6613\u4e8e\u7406\u89e3\u7684\u65b9\u5f0f\u53bb\u56de\u7b54\u95ee\u9898\u3002\\\n", "\u5f53\u4f60\u4e0d\u77e5\u9053\u95ee\u9898\u7684\u7b54\u6848\u65f6\uff0c\u4f60\u627f\u8ba4\\\n", "\u4f60\u4e0d\u77e5\u9053.\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e8c\u4e2a\u63d0\u793a\u9002\u5408\u56de\u7b54\u6570\u5b66\u95ee\u9898\n", "math_template = \"\"\"\u4f60\u662f\u4e00\u4e2a\u975e\u5e38\u4f18\u79c0\u7684\u6570\u5b66\u5bb6\u3002 \\\n", "\u4f60\u64c5\u957f\u56de\u7b54\u6570\u5b66\u95ee\u9898\u3002 \\\n", "\u4f60\u4e4b\u6240\u4ee5\u5982\u6b64\u4f18\u79c0\uff0c \\\n", "\u662f\u56e0\u4e3a\u4f60\u80fd\u591f\u5c06\u68d8\u624b\u7684\u95ee\u9898\u5206\u89e3\u4e3a\u7ec4\u6210\u90e8\u5206\uff0c\\\n", "\u56de\u7b54\u7ec4\u6210\u90e8\u5206\uff0c\u7136\u540e\u5c06\u5b83\u4eec\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u56de\u7b54\u66f4\u5e7f\u6cdb\u7684\u95ee\u9898\u3002\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898\uff1a\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u4e09\u4e2a\u9002\u5408\u56de\u7b54\u5386\u53f2\u95ee\u9898\n", "history_template = \"\"\"\u4f60\u662f\u4ee5\u4e3a\u975e\u5e38\u4f18\u79c0\u7684\u5386\u53f2\u5b66\u5bb6\u3002 \\\n", "\u4f60\u5bf9\u4e00\u7cfb\u5217\u5386\u53f2\u65f6\u671f\u7684\u4eba\u7269\u3001\u4e8b\u4ef6\u548c\u80cc\u666f\u6709\u7740\u6781\u597d\u7684\u5b66\u8bc6\u548c\u7406\u89e3\\\n", "\u4f60\u6709\u80fd\u529b\u601d\u8003\u3001\u53cd\u601d\u3001\u8fa9\u8bc1\u3001\u8ba8\u8bba\u548c\u8bc4\u4f30\u8fc7\u53bb\u3002\\\n", "\u4f60\u5c0a\u91cd\u5386\u53f2\u8bc1\u636e\uff0c\u5e76\u6709\u80fd\u529b\u5229\u7528\u5b83\u6765\u652f\u6301\u4f60\u7684\u89e3\u91ca\u548c\u5224\u65ad\u3002\n", "\n", "\u8fd9\u662f\u4e00\u4e2a\u95ee\u9898:\n", "{input}\"\"\"\n", "\n", "\n", "#\u7b2c\u56db\u4e2a\u9002\u5408\u56de\u7b54\u8ba1\u7b97\u673a\u95ee\u9898\n", "computerscience_template = \"\"\" \u4f60\u662f\u4e00\u4e2a\u6210\u529f\u7684\u8ba1\u7b97\u673a\u79d1\u5b66\u4e13\u5bb6\u3002\\\n", "\u4f60\u6709\u521b\u9020\u529b\u3001\u534f\u4f5c\u7cbe\u795e\u3001\\\n", "\u524d\u77bb\u6027\u601d\u7ef4\u3001\u81ea\u4fe1\u3001\u89e3\u51b3\u95ee\u9898\u7684\u80fd\u529b\u3001\\\n", "\u5bf9\u7406\u8bba\u548c\u7b97\u6cd5\u7684\u7406\u89e3\u4ee5\u53ca\u51fa\u8272\u7684\u6c9f\u901a\u6280\u5de7\u3002\\\n", "\u4f60\u975e\u5e38\u64c5\u957f\u56de\u7b54\u7f16\u7a0b\u95ee\u9898\u3002\\\n", "\u4f60\u4e4b\u6240\u4ee5\u5982\u6b64\u4f18\u79c0\uff0c\u662f\u56e0\u4e3a\u4f60\u77e5\u9053 \\\n", "\u5982\u4f55\u901a\u8fc7\u4ee5\u673a\u5668\u53ef\u4ee5\u8f7b\u677e\u89e3\u91ca\u7684\u547d\u4ee4\u5f0f\u6b65\u9aa4\u63cf\u8ff0\u89e3\u51b3\u65b9\u6848\u6765\u89e3\u51b3\u95ee\u9898\uff0c\\\n", "\u5e76\u4e14\u4f60\u77e5\u9053\u5982\u4f55\u9009\u62e9\u5728\u65f6\u95f4\u590d\u6742\u6027\u548c\u7a7a\u95f4\u590d\u6742\u6027\u4e4b\u95f4\u53d6\u5f97\u826f\u597d\u5e73\u8861\u7684\u89e3\u51b3\u65b9\u6848\u3002\n", "\n", "\u8fd9\u8fd8\u662f\u4e00\u4e2a\u8f93\u5165\uff1a\n", "{input}\"\"\""]}, {"cell_type": "code", "execution_count": 52, "id": "deb8aafc", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "prompt_infos = [\n", " {\n", " \"\u540d\u5b57\": \"\u7269\u7406\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u5173\u4e8e\u7269\u7406\u5b66\u7684\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": physics_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u6570\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u6570\u5b66\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": math_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u5386\u53f2\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u5386\u53f2\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": history_template\n", " },\n", " {\n", " \"\u540d\u5b57\": \"\u8ba1\u7b97\u673a\u79d1\u5b66\", \n", " \"\u63cf\u8ff0\": \"\u64c5\u957f\u56de\u7b54\u8ba1\u7b97\u673a\u79d1\u5b66\u95ee\u9898\", \n", " \"\u63d0\u793a\u6a21\u677f\": computerscience_template\n", " }\n", "]\n"]}, {"cell_type": "code", "execution_count": null, "id": "fd6eb641", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "destination_chains = {}\n", "for p_info in prompt_infos:\n", " name = p_info[\"\u540d\u5b57\"]\n", " prompt_template = p_info[\"\u63d0\u793a\u6a21\u677f\"]\n", " prompt = ChatPromptTemplate.from_template(template=prompt_template)\n", " chain = LLMChain(llm=llm, prompt=prompt)\n", " destination_chains[name] = chain \n", " \n", "destinations = [f\"{p['\u540d\u5b57']}: {p['\u63cf\u8ff0']}\" for p in prompt_infos]\n", "destinations_str = \"\\n\".join(destinations)"]}, {"cell_type": "code", "execution_count": null, "id": "af088d6b-a70b-4cd7-bc6e-4ad7b32e6ae1", "metadata": {}, "outputs": [], "source": ["default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n", "default_chain = LLMChain(llm=llm, prompt=default_prompt)"]}, {"cell_type": "code", "execution_count": null, "id": "a7aae035", "metadata": {}, "outputs": [], "source": ["# \u4e2d\u6587\n", "\n", "# \u591a\u63d0\u793a\u8def\u7531\u6a21\u677f\n", "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"\u7ed9\u8bed\u8a00\u6a21\u578b\u4e00\u4e2a\u539f\u59cb\u6587\u672c\u8f93\u5165\uff0c\\\n", "\u8ba9\u5176\u9009\u62e9\u6700\u9002\u5408\u8f93\u5165\u7684\u6a21\u578b\u63d0\u793a\u3002\\\n", "\u7cfb\u7edf\u5c06\u4e3a\u60a8\u63d0\u4f9b\u53ef\u7528\u63d0\u793a\u7684\u540d\u79f0\u4ee5\u53ca\u6700\u9002\u5408\u6539\u63d0\u793a\u7684\u63cf\u8ff0\u3002\\\n", "\u5982\u679c\u4f60\u8ba4\u4e3a\u4fee\u6539\u539f\u59cb\u8f93\u5165\u6700\u7ec8\u4f1a\u5bfc\u81f4\u8bed\u8a00\u6a21\u578b\u505a\u51fa\u66f4\u597d\u7684\u54cd\u5e94\uff0c\\\n", "\u4f60\u4e5f\u53ef\u4ee5\u4fee\u6539\u539f\u59cb\u8f93\u5165\u3002\n", "\n", "\n", "<< \u683c\u5f0f >>\n", "\u8fd4\u56de\u4e00\u4e2a\u5e26\u6709JSON\u5bf9\u8c61\u7684markdown\u4ee3\u7801\u7247\u6bb5\uff0c\u8be5JSON\u5bf9\u8c61\u7684\u683c\u5f0f\u5982\u4e0b\uff1a\n", "```json\n", "{{{{\n", " \"destination\": \u5b57\u7b26\u4e32 \\ \u4f7f\u7528\u7684\u63d0\u793a\u540d\u5b57\u6216\u8005\u4f7f\u7528 \"DEFAULT\"\n", " \"next_inputs\": \u5b57\u7b26\u4e32 \\ \u539f\u59cb\u8f93\u5165\u7684\u6539\u8fdb\u7248\u672c\n", "}}}}\n", "```\n", "\n", "\n", "\u8bb0\u4f4f\uff1a\u201cdestination\u201d\u5fc5\u987b\u662f\u4e0b\u9762\u6307\u5b9a\u7684\u5019\u9009\u63d0\u793a\u540d\u79f0\u4e4b\u4e00\uff0c\\\n", "\u6216\u8005\u5982\u679c\u8f93\u5165\u4e0d\u592a\u9002\u5408\u4efb\u4f55\u5019\u9009\u63d0\u793a\uff0c\\\n", "\u5219\u53ef\u4ee5\u662f \u201cDEFAULT\u201d \u3002\n", "\u8bb0\u4f4f\uff1a\u5982\u679c\u60a8\u8ba4\u4e3a\u4e0d\u9700\u8981\u4efb\u4f55\u4fee\u6539\uff0c\\\n", "\u5219 \u201cnext_inputs\u201d \u53ef\u4ee5\u53ea\u662f\u539f\u59cb\u8f93\u5165\u3002\n", "\n", "<< \u5019\u9009\u63d0\u793a >>\n", "{destinations}\n", "\n", "<< \u8f93\u5165 >>\n", "{{input}}\n", "\n", "<< \u8f93\u51fa (\u8bb0\u5f97\u8981\u5305\u542b ```json)>>\n", "\n", "\u6837\u4f8b:\n", "<< \u8f93\u5165 >>\n", "\"\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04?\"\n", "<< \u8f93\u51fa >>\n", "```json\n", "{{{{\n", " \"destination\": \u5b57\u7b26\u4e32 \\ \u4f7f\u7528\u7684\u63d0\u793a\u540d\u5b57\u6216\u8005\u4f7f\u7528 \"DEFAULT\"\n", " \"next_inputs\": \u5b57\u7b26\u4e32 \\ \u539f\u59cb\u8f93\u5165\u7684\u6539\u8fdb\u7248\u672c\n", "}}}}\n", "```\n", "\n", "\"\"\""]}, {"cell_type": "code", "execution_count": null, "id": "7470b25c-ef82-496c-a6e0-e04b99b08e70", "metadata": {}, "outputs": [], "source": ["#\u591a\u63d0\u793a\u94fe\n", "chain = MultiPromptChain(router_chain=router_chain, #l\u8def\u7531\u94fe\u8def\n", " destination_chains=destination_chains, #\u76ee\u6807\u94fe\u8def\n", " default_chain=default_chain, #\u9ed8\u8ba4\u94fe\u8def\n", " verbose=True \n", " )"]}, {"cell_type": "code", "execution_count": 36, "id": "4446724c", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "physics: {'input': '\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u9ed1\u4f53\u8f90\u5c04\u662f\u6307\u4e00\u4e2a\u7406\u60f3\u5316\u7684\u7269\u4f53\uff0c\u5b83\u80fd\u591f\u5b8c\u5168\u5438\u6536\u6240\u6709\u5165\u5c04\u5230\u5b83\u8868\u9762\u7684\u8f90\u5c04\u80fd\u91cf\uff0c\u5e76\u4ee5\u70ed\u8f90\u5c04\u7684\u5f62\u5f0f\u91cd\u65b0\u53d1\u5c04\u51fa\u6765\u3002\u9ed1\u4f53\u8f90\u5c04\u7684\u7279\u70b9\u662f\u5176\u8f90\u5c04\u80fd\u91cf\u7684\u5206\u5e03\u4e0e\u6e29\u5ea6\u6709\u5173\uff0c\u968f\u7740\u6e29\u5ea6\u7684\u5347\u9ad8\uff0c\u8f90\u5c04\u80fd\u91cf\u7684\u5cf0\u503c\u4f1a\u5411\u66f4\u77ed\u7684\u6ce2\u957f\u65b9\u5411\u79fb\u52a8\u3002\u8fd9\u4e2a\u73b0\u8c61\u88ab\u79f0\u4e3a\u9ed1\u4f53\u8f90\u5c04\u8c31\u7684\u4f4d\u79fb\u5b9a\u5f8b\uff0c\u7531\u666e\u6717\u514b\u572820\u4e16\u7eaa\u521d\u63d0\u51fa\u3002\u9ed1\u4f53\u8f90\u5c04\u5728\u7814\u7a76\u70ed\u529b\u5b66\u3001\u91cf\u5b50\u529b\u5b66\u548c\u5b87\u5b99\u5b66\u7b49\u9886\u57df\u4e2d\u5177\u6709\u91cd\u8981\u7684\u5e94\u7528\u3002'"]}, "execution_count": 36, "metadata": {}, "output_type": "execute_result"}], "source": ["#\u4e2d\u6587\n", "chain.run(\"\u4ec0\u4e48\u662f\u9ed1\u4f53\u8f90\u5c04\uff1f\")"]}, {"cell_type": "code", "execution_count": 41, "id": "ef81eda3", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "History: {'input': '\u4f60\u77e5\u9053\u674e\u767d\u662f\u8c01\u561b?'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u674e\u767d\u662f\u5510\u671d\u65f6\u671f\u7684\u4e00\u4f4d\u8457\u540d\u8bd7\u4eba\u3002\u4ed6\u7684\u8bd7\u6b4c\u4ee5\u8c6a\u653e\u3001\u5954\u653e\u3001\u81ea\u7531\u7684\u98ce\u683c\u8457\u79f0\uff0c\u88ab\u8a89\u4e3a\u201c\u8bd7\u4ed9\u201d\u3002\u4ed6\u7684\u4f5c\u54c1\u6d89\u53ca\u5e7f\u6cdb\uff0c\u5305\u62ec\u5c71\u6c34\u7530\u56ed\u3001\u5386\u53f2\u4f20\u8bf4\u3001\u54f2\u7406\u601d\u8003\u7b49\u591a\u4e2a\u65b9\u9762\uff0c\u5bf9\u4e2d\u56fd\u53e4\u5178\u6587\u5b66\u7684\u53d1\u5c55\u4ea7\u751f\u4e86\u6df1\u8fdc\u7684\u5f71\u54cd\u3002'"]}, "execution_count": 41, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"\u4f60\u77e5\u9053\u674e\u767d\u662f\u8c01\u561b?\")"]}, {"cell_type": "code", "execution_count": 37, "id": "795bea17", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "math: {'input': '2 + 2 \u7b49\u4e8e\u591a\u5c11'}"]}, {"name": "stderr", "output_type": "stream", "text": ["Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 1.0 seconds as it raised ServiceUnavailableError: The server is overloaded or not ready yet..\n"]}, {"name": "stdout", "output_type": "stream", "text": ["\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'2 + 2 \u7b49\u4e8e 4\u3002'"]}, "execution_count": 37, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"2 + 2 \u7b49\u4e8e\u591a\u5c11\")"]}, {"cell_type": "code", "execution_count": 38, "id": "a64d0759", "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["\n", "\n", "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n", "None: {'input': '\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f'}\n", "\u001b[1m> Finished chain.\u001b[0m\n"]}, {"data": {"text/plain": ["'\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff0c\u662f\u56e0\u4e3aDNA\u662f\u9057\u4f20\u4fe1\u606f\u7684\u8f7d\u4f53\u3002DNA\u662f\u7531\u56db\u79cd\u78b1\u57fa\uff08\u817a\u560c\u5464\u3001\u9e1f\u560c\u5464\u3001\u80f8\u817a\u5627\u5576\u548c\u9cde\u560c\u5464\uff09\u7ec4\u6210\u7684\u957f\u94fe\u72b6\u5206\u5b50\uff0c\u5b83\u5b58\u50a8\u4e86\u751f\u7269\u4f53\u7684\u9057\u4f20\u4fe1\u606f\uff0c\u5305\u62ec\u4e2a\u4f53\u7684\u7279\u5f81\u3001\u751f\u957f\u53d1\u80b2\u3001\u4ee3\u8c22\u529f\u80fd\u7b49\u3002\u6bcf\u4e2a\u7ec6\u80de\u90fd\u9700\u8981\u8fd9\u4e9b\u9057\u4f20\u4fe1\u606f\u6765\u6267\u884c\u5176\u7279\u5b9a\u7684\u529f\u80fd\u548c\u4efb\u52a1\uff0c\u56e0\u6b64\u6bcf\u4e2a\u7ec6\u80de\u90fd\u9700\u8981\u5305\u542bDNA\u3002\u6b64\u5916\uff0cDNA\u8fd8\u80fd\u901a\u8fc7\u590d\u5236\u548c\u4f20\u9012\u7ed9\u4e0b\u4e00\u4ee3\u7ec6\u80de\u548c\u4e2a\u4f53\uff0c\u4ee5\u4fdd\u8bc1\u9057\u4f20\u4fe1\u606f\u7684\u4f20\u627f\u3002'"]}, "execution_count": 38, "metadata": {}, "output_type": "execute_result"}], "source": ["# \u4e2d\u6587\n", "chain.run(\"\u4e3a\u4ec0\u4e48\u6211\u4eec\u8eab\u4f53\u91cc\u7684\u6bcf\u4e2a\u7ec6\u80de\u90fd\u5305\u542bDNA\uff1f\")"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12"}}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file From ad139827878c3db110ef32bca0646eaa1881a537 Mon Sep 17 00:00:00 2001 From: joyenjoye Date: Sun, 16 Jul 2023 23:10:30 +0800 Subject: [PATCH 5/5] Update Chapter 5 --- ...5.基于文档的问答 Question and Answer.ipynb | 926 +++++++++++++++++- 1 file changed, 925 insertions(+), 1 deletion(-) diff --git a/content/LangChain for LLM Application Development/5.基于文档的问答 Question and Answer.ipynb b/content/LangChain for LLM Application Development/5.基于文档的问答 Question and Answer.ipynb index f8f9719..60bc045 100644 --- a/content/LangChain for LLM Application Development/5.基于文档的问答 Question and Answer.ipynb +++ b/content/LangChain for LLM Application Development/5.基于文档的问答 Question and Answer.ipynb @@ -1 +1,925 @@ -{"cells":[{"cell_type":"markdown","id":"f200ba9a","metadata":{},"source":["# 第五章 基于文档的问答\n","\n"," - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n"," - [一、导入embedding模型和向量存储组件](#一、导入embedding模型和向量存储组件)\n"," - [1.1 创建向量存储](#1.1-创建向量存储)\n"," - [1.2 使用语言模型与文档结合使用](#1.2-使用语言模型与文档结合使用)\n"," - [二、 如何回答我们文档的相关问题](#二、-如何回答我们文档的相关问题)\n"]},{"cell_type":"markdown","id":"52824b89-532a-4e54-87e9-1410813cd39e","metadata":{},"source":["\n","本章内容主要利用langchain构建向量数据库,可以在文档上方或关于文档回答问题,因此,给定从PDF文件、网页或某些公司的内部文档收集中提取的文本,使用llm回答有关这些文档内容的问题"]},{"cell_type":"markdown","id":"42ccf132-cfab-4153-97b5-d545faae4d36","metadata":{"tags":[]},"source":["## 一、设置OpenAI API Key\n","\n","登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n","\n","- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n","- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n","\n","

\n"," OPENAI_API_KEY=\"your_api_key\" \n","

\n"," \n"," 替换\"your_api_key\"为你自己的 API Key"]},{"cell_type":"code","execution_count":1,"id":"cc33ceb1-535f-454d-988c-347a8b14fd72","metadata":{},"outputs":[],"source":["# 下载需要的包python-dotenv和openai\n","# 如果你需要查看安装过程日志,可删除 -q \n","!pip install -q python-dotenv\n","!pip install -q openai"]},{"cell_type":"code","execution_count":2,"id":"e3c97235-f101-47f2-92db-1c37f4bf9845","metadata":{"tags":[]},"outputs":[],"source":["import os\n","import openai\n","from dotenv import load_dotenv, find_dotenv\n","\n","# 读取本地/项目的环境变量。\n","\n","# find_dotenv()寻找并定位.env文件的路径\n","# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中 \n","# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n","_ = load_dotenv(find_dotenv())\n","\n","# 获取环境变量 OPENAI_API_KEY\n","openai.api_key = os.environ['OPENAI_API_KEY'] "]},{"cell_type":"code","execution_count":52,"id":"af8c3c96","metadata":{},"outputs":[{"data":{"text/plain":["'\\n\\n人工智能是一项极具前景的技术,它的发展正在改变人类的生活方式,带来了无数的便利,也被认为是未来发展的重要标志。人工智能的发展让许多复杂的任务变得更加容易,更高效的完成,节省了大量的时间和精力,为人类发展带来了极大的帮助。'"]},"execution_count":52,"metadata":{},"output_type":"execute_result"}],"source":["from langchain.llms import OpenAI\n","\n","llm = OpenAI(model_name=\"text-davinci-003\",max_tokens=1024)\n","llm(\"怎么评价人工智能\")"]},{"cell_type":"markdown","id":"8cb7a7ec","metadata":{"height":30},"source":["## 一、导入embedding模型和向量存储组件\n","使用Dock Array内存搜索向量存储,作为一个内存向量存储,不需要连接外部数据库"]},{"cell_type":"code","execution_count":3,"id":"974acf8e-8f88-42de-88f8-40a82cb58e8b","metadata":{"height":98},"outputs":[],"source":["from langchain.chains import RetrievalQA #检索QA链,在文档上进行检索\n","from langchain.chat_models import ChatOpenAI #openai模型\n","from langchain.document_loaders import CSVLoader #文档加载器,采用csv格式存储\n","from langchain.vectorstores import DocArrayInMemorySearch #向量存储\n","from IPython.display import display, Markdown #在jupyter显示信息的工具"]},{"cell_type":"code","execution_count":4,"id":"7249846e","metadata":{"height":75},"outputs":[],"source":["#读取文件\n","file = 'OutdoorClothingCatalog_1000.csv'\n","loader = CSVLoader(file_path=file)"]},{"cell_type":"code","execution_count":24,"id":"7724f00e","metadata":{"height":30},"outputs":[{"data":{"text/html":["
\n","\n","\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
012
0NaNnamedescription
10.0Women's Campside OxfordsThis ultracomfortable lace-to-toe Oxford boast...
21.0Recycled Waterhog Dog Mat, Chevron WeaveProtect your floors from spills and splashing ...
32.0Infant and Toddler Girls' Coastal Chill Swimsu...She'll love the bright colors, ruffles and exc...
43.0Refresh Swimwear, V-Neck Tankini ContrastsWhether you're going for a swim or heading out...
............
996995.0Men's Classic Denim, Standard FitCrafted from premium denim that will last wash...
997996.0CozyPrint Sweater Fleece PulloverThe ultimate sweater fleece - made from superi...
998997.0Women's NRS Endurance Spray Paddling PantsThese comfortable and affordable splash paddli...
999998.0Women's Stop Flies HoodieThis great-looking hoodie uses No Fly Zone Tec...
1000999.0Modern Utility BagThis US-made crossbody bag is built with the s...
\n","

1001 rows × 3 columns

\n","
"],"text/plain":[" 0 1 \n","0 NaN name \\\n","1 0.0 Women's Campside Oxfords \n","2 1.0 Recycled Waterhog Dog Mat, Chevron Weave \n","3 2.0 Infant and Toddler Girls' Coastal Chill Swimsu... \n","4 3.0 Refresh Swimwear, V-Neck Tankini Contrasts \n","... ... ... \n","996 995.0 Men's Classic Denim, Standard Fit \n","997 996.0 CozyPrint Sweater Fleece Pullover \n","998 997.0 Women's NRS Endurance Spray Paddling Pants \n","999 998.0 Women's Stop Flies Hoodie \n","1000 999.0 Modern Utility Bag \n","\n"," 2 \n","0 description \n","1 This ultracomfortable lace-to-toe Oxford boast... \n","2 Protect your floors from spills and splashing ... \n","3 She'll love the bright colors, ruffles and exc... \n","4 Whether you're going for a swim or heading out... \n","... ... \n","996 Crafted from premium denim that will last wash... \n","997 The ultimate sweater fleece - made from superi... \n","998 These comfortable and affordable splash paddli... \n","999 This great-looking hoodie uses No Fly Zone Tec... \n","1000 This US-made crossbody bag is built with the s... \n","\n","[1001 rows x 3 columns]"]},"execution_count":24,"metadata":{},"output_type":"execute_result"}],"source":["#查看数据\n","import pandas as pd\n","data = pd.read_csv(file,header=None)\n","data"]},{"cell_type":"markdown","id":"3bd6422c","metadata":{},"source":["提供了一个户外服装的CSV文件,我们将使用它与语言模型结合使用"]},{"cell_type":"markdown","id":"2963fc63","metadata":{},"source":["### 1.1 创建向量存储\n","将导入一个索引,即向量存储索引创建器"]},{"cell_type":"code","execution_count":25,"id":"5bfaba30","metadata":{"height":30},"outputs":[],"source":["from langchain.indexes import VectorstoreIndexCreator #导入向量存储索引创建器"]},{"cell_type":"code","execution_count":null,"id":"9e200726","metadata":{"height":64},"outputs":[],"source":["'''\n","将指定向量存储类,创建完成后,我们将从加载器中调用,通过文档记载器列表加载\n","'''\n","\n","index = VectorstoreIndexCreator(\n"," vectorstore_cls=DocArrayInMemorySearch\n",").from_loaders([loader])"]},{"cell_type":"code","execution_count":9,"id":"34562d81","metadata":{"height":47},"outputs":[],"source":["query =\"Please list all your shirts with sun protection \\\n","in a table in markdown and summarize each one.\""]},{"cell_type":"code","execution_count":21,"id":"cfd0cc37","metadata":{"height":30},"outputs":[],"source":["response = index.query(query)#使用索引查询创建一个响应,并传入这个查询"]},{"cell_type":"code","execution_count":23,"id":"ae21f1ff","metadata":{"height":30,"scrolled":true},"outputs":[{"data":{"text/markdown":["\n","\n","| Name | Description |\n","| --- | --- |\n","| Men's Tropical Plaid Short-Sleeve Shirt | UPF 50+ rated, 100% polyester, wrinkle-resistant, front and back cape venting, two front bellows pockets |\n","| Men's Plaid Tropic Shirt, Short-Sleeve | UPF 50+ rated, 52% polyester and 48% nylon, machine washable and dryable, front and back cape venting, two front bellows pockets |\n","| Men's TropicVibe Shirt, Short-Sleeve | UPF 50+ rated, 71% Nylon, 29% Polyester, 100% Polyester knit mesh, machine wash and dry, front and back cape venting, two front bellows pockets |\n","| Sun Shield Shirt by | UPF 50+ rated, 78% nylon, 22% Lycra Xtra Life fiber, handwash, line dry, wicks moisture, fits comfortably over swimsuit, abrasion resistant |\n","\n","All four shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. The Men's Tropical Plaid Short-Sleeve Shirt is made of 100% polyester and is wrinkle-resistant"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["display(Markdown(response))#查看查询返回的内容"]},{"cell_type":"markdown","id":"eb74cc79","metadata":{},"source":["得到了一个Markdown表格,其中包含所有带有防晒衣的衬衫的名称和描述,还得到了一个语言模型提供的不错的小总结"]},{"cell_type":"markdown","id":"dd34e50e","metadata":{},"source":["### 1.2 使用语言模型与文档结合使用\n","想要使用语言模型并将其与我们的许多文档结合使用,但是语言模型一次只能检查几千个单词,如果我们有非常大的文档,如何让语言模型回答关于其中所有内容的问题呢?通过embedding和向量存储实现\n","* embedding \n","文本片段创建数值表示文本语义,相似内容的文本片段将具有相似的向量,这使我们可以在向量空间中比较文本片段\n","* 向量数据库 \n","向量数据库是存储我们在上一步中创建的这些向量表示的一种方式,我们创建这个向量数据库的方式是用来自传入文档的文本块填充它。\n","当我们获得一个大的传入文档时,我们首先将其分成较小的块,因为我们可能无法将整个文档传递给语言模型,因此采用分块embedding的方式储存到向量数据库中。这就是创建索引的过程。\n","\n","通过运行时使用索引来查找与传入查询最相关的文本片段,然后我们将其与向量数据库中的所有向量进行比较,并选择最相似的n个,返回语言模型得到最终答案"]},{"cell_type":"code","execution_count":26,"id":"631396c6","metadata":{"height":30},"outputs":[],"source":["#创建一个文档加载器,通过csv格式加载\n","loader = CSVLoader(file_path=file)\n","docs = loader.load()"]},{"cell_type":"code","execution_count":27,"id":"4a977f44","metadata":{"height":30},"outputs":[{"data":{"text/plain":["Document(page_content=\": 0\\nname: Women's Campside Oxfords\\ndescription: This ultracomfortable lace-to-toe Oxford boasts a super-soft canvas, thick cushioning, and quality construction for a broken-in feel from the first time you put them on. \\n\\nSize & Fit: Order regular shoe size. For half sizes not offered, order up to next whole size. \\n\\nSpecs: Approx. weight: 1 lb.1 oz. per pair. \\n\\nConstruction: Soft canvas material for a broken-in feel and look. Comfortable EVA innersole with Cleansport NXT® antimicrobial odor control. Vintage hunt, fish and camping motif on innersole. Moderate arch contour of innersole. EVA foam midsole for cushioning and support. Chain-tread-inspired molded rubber outsole with modified chain-tread pattern. Imported. \\n\\nQuestions? Please contact us for any inquiries.\", metadata={'source': 'OutdoorClothingCatalog_1000.csv', 'row': 0})"]},"execution_count":27,"metadata":{},"output_type":"execute_result"}],"source":["docs[0]#查看单个文档,我们可以看到每个文档对应于CSV中的一个块"]},{"cell_type":"code","execution_count":31,"id":"e875693a","metadata":{"height":47},"outputs":[],"source":["'''\n","因为这些文档已经非常小了,所以我们实际上不需要在这里进行任何分块,可以直接进行embedding\n","'''\n","\n","from langchain.embeddings import OpenAIEmbeddings #要创建可以直接进行embedding,我们将使用OpenAI的可以直接进行embedding类\n","embeddings = OpenAIEmbeddings() #初始化"]},{"cell_type":"code","execution_count":32,"id":"779bec75","metadata":{"height":30},"outputs":[],"source":["embed = embeddings.embed_query(\"Hi my name is Harrison\")#让我们使用embedding上的查询方法为特定文本创建embedding"]},{"cell_type":"code","execution_count":33,"id":"699aaaf9","metadata":{"height":30},"outputs":[{"name":"stdout","output_type":"stream","text":["1536\n"]}],"source":["print(len(embed))#查看这个embedding,我们可以看到有超过一千个不同的元素"]},{"cell_type":"code","execution_count":34,"id":"9d00d346","metadata":{"height":30},"outputs":[{"name":"stdout","output_type":"stream","text":["[-0.021933607757091522, 0.006697045173496008, -0.01819835603237152, -0.039113257080316544, -0.014060650952160358]\n"]}],"source":["print(embed[:5])#每个元素都是不同的数字值,组合起来,这就创建了这段文本的总体数值表示"]},{"cell_type":"code","execution_count":35,"id":"27ad0bb0","metadata":{"height":81},"outputs":[],"source":["'''\n","为刚才的文本创建embedding,准备将它们存储在向量存储中,使用向量存储上的from documents方法来实现。\n","该方法接受文档列表、嵌入对象,然后我们将创建一个总体向量存储\n","'''\n","db = DocArrayInMemorySearch.from_documents(\n"," docs, \n"," embeddings\n",")"]},{"cell_type":"code","execution_count":36,"id":"0329bfd5","metadata":{"height":30},"outputs":[],"source":["query = \"Please suggest a shirt with sunblocking\""]},{"cell_type":"code","execution_count":37,"id":"7909c6b7","metadata":{"height":30},"outputs":[],"source":["docs = db.similarity_search(query)#使用这个向量存储来查找与传入查询类似的文本,如果我们在向量存储中使用相似性搜索方法并传入一个查询,我们将得到一个文档列表"]},{"cell_type":"code","execution_count":38,"id":"43321853","metadata":{"height":30},"outputs":[{"data":{"text/plain":["4"]},"execution_count":38,"metadata":{},"output_type":"execute_result"}],"source":["len(docs)# 我们可以看到它返回了四个文档"]},{"cell_type":"code","execution_count":39,"id":"6eba90b5","metadata":{"height":30},"outputs":[{"data":{"text/plain":["Document(page_content=': 255\\nname: Sun Shield Shirt by\\ndescription: \"Block the sun, not the fun – our high-performance sun shirt is guaranteed to protect from harmful UV rays. \\n\\nSize & Fit: Slightly Fitted: Softly shapes the body. Falls at hip.\\n\\nFabric & Care: 78% nylon, 22% Lycra Xtra Life fiber. UPF 50+ rated – the highest rated sun protection possible. Handwash, line dry.\\n\\nAdditional Features: Wicks moisture for quick-drying comfort. Fits comfortably over your favorite swimsuit. Abrasion resistant for season after season of wear. Imported.\\n\\nSun Protection That Won\\'t Wear Off\\nOur high-performance fabric provides SPF 50+ sun protection, blocking 98% of the sun\\'s harmful rays. This fabric is recommended by The Skin Cancer Foundation as an effective UV protectant.', metadata={'source': 'OutdoorClothingCatalog_1000.csv', 'row': 255})"]},"execution_count":39,"metadata":{},"output_type":"execute_result"}],"source":["docs[0] #,如果我们看第一个文档,我们可以看到它确实是一件关于防晒的衬衫"]},{"cell_type":"markdown","id":"fe41b36f","metadata":{},"source":["## 二、 如何回答我们文档的相关问题\n","首先,我们需要从这个向量存储中创建一个检索器,检索器是一个通用接口,可以由任何接受查询并返回文档的方法支持。接下来,因为我们想要进行文本生成并返回自然语言响应\n"]},{"cell_type":"code","execution_count":40,"id":"c0c3596e","metadata":{"height":30},"outputs":[],"source":["retriever = db.as_retriever() #创建检索器通用接口"]},{"cell_type":"code","execution_count":55,"id":"0625f5e8","metadata":{"height":47},"outputs":[],"source":["llm = ChatOpenAI(temperature = 0.0,max_tokens=1024) #导入语言模型\n"]},{"cell_type":"code","execution_count":43,"id":"a573f58a","metadata":{"height":47},"outputs":[],"source":["qdocs = \"\".join([docs[i].page_content for i in range(len(docs))]) # 将合并文档中的所有页面内容到一个变量中\n"]},{"cell_type":"code","execution_count":null,"id":"14682d95","metadata":{"height":64},"outputs":[],"source":["response = llm.call_as_llm(f\"{qdocs} Question: Please list all your \\\n","shirts with sun protection in a table in markdown and summarize each one.\") #列出所有具有防晒功能的衬衫并在Markdown表格中总结每个衬衫的语言模型\n"]},{"cell_type":"code","execution_count":28,"id":"8bba545b","metadata":{"height":30},"outputs":[{"data":{"text/markdown":["| Name | Description |\n","| --- | --- |\n","| Sun Shield Shirt | High-performance sun shirt with UPF 50+ sun protection, moisture-wicking, and abrasion-resistant fabric. Recommended by The Skin Cancer Foundation. |\n","| Men's Plaid Tropic Shirt | Ultracomfortable shirt with UPF 50+ sun protection, wrinkle-free fabric, and front/back cape venting. Made with 52% polyester and 48% nylon. |\n","| Men's TropicVibe Shirt | Men's sun-protection shirt with built-in UPF 50+ and front/back cape venting. Made with 71% nylon and 29% polyester. |\n","| Men's Tropical Plaid Short-Sleeve Shirt | Lightest hot-weather shirt with UPF 50+ sun protection, front/back cape venting, and two front bellows pockets. Made with 100% polyester and is wrinkle-resistant. |\n","\n","All of these shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. They are made with high-performance fabrics that are moisture-wicking, wrinkle-resistant, and abrasion-resistant. The Men's Plaid Tropic Shirt and Men's Tropical Plaid Short-Sleeve Shirt both have front/back cape venting for added breathability. The Sun Shield Shirt is recommended by The Skin Cancer Foundation as an effective UV protectant."],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["display(Markdown(response))"]},{"cell_type":"markdown","id":"12f042e7","metadata":{},"source":["在此处打印响应,我们可以看到我们得到了一个表格,正如我们所要求的那样"]},{"cell_type":"code","execution_count":56,"id":"32c94d22","metadata":{"height":115},"outputs":[],"source":["''' \n","通过LangChain链封装起来\n","创建一个检索QA链,对检索到的文档进行问题回答,要创建这样的链,我们将传入几个不同的东西\n","1、语言模型,在最后进行文本生成\n","2、传入链类型,这里使用stuff,将所有文档塞入上下文并对语言模型进行一次调用\n","3、传入一个检索器\n","'''\n","\n","\n","qa_stuff = RetrievalQA.from_chain_type(\n"," llm=llm, \n"," chain_type=\"stuff\", \n"," retriever=retriever, \n"," verbose=True\n",")"]},{"cell_type":"code","execution_count":46,"id":"e4769316","metadata":{"height":47},"outputs":[],"source":["query = \"Please list all your shirts with sun protection in a table \\\n","in markdown and summarize each one.\"#创建一个查询并在此查询上运行链"]},{"cell_type":"code","execution_count":null,"id":"1fc3c2f3","metadata":{"height":30},"outputs":[],"source":["response = qa_stuff.run(query)"]},{"cell_type":"code","execution_count":58,"id":"fba1a5db","metadata":{"height":30},"outputs":[{"data":{"text/markdown":["\n","\n","| Name | Description |\n","| --- | --- |\n","| Men's Tropical Plaid Short-Sleeve Shirt | UPF 50+ rated, 100% polyester, wrinkle-resistant, front and back cape venting, two front bellows pockets |\n","| Men's Plaid Tropic Shirt, Short-Sleeve | UPF 50+ rated, 52% polyester and 48% nylon, machine washable and dryable, front and back cape venting, two front bellows pockets |\n","| Men's TropicVibe Shirt, Short-Sleeve | UPF 50+ rated, 71% Nylon, 29% Polyester, 100% Polyester knit mesh, machine wash and dry, front and back cape venting, two front bellows pockets |\n","| Sun Shield Shirt by | UPF 50+ rated, 78% nylon, 22% Lycra Xtra Life fiber, handwash, line dry, wicks moisture, fits comfortably over swimsuit, abrasion resistant |\n","\n","All four shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. The Men's Tropical Plaid Short-Sleeve Shirt is made of 100% polyester and is wrinkle-resistant"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["display(Markdown(response))#使用 display 和 markdown 显示它"]},{"cell_type":"markdown","id":"e28c5657","metadata":{},"source":["这两个方式返回相同的结果"]},{"cell_type":"markdown","id":"44f1fa38","metadata":{},"source":["想在许多不同类型的块上执行相同类型的问答,该怎么办?之前的实验中只返回了4个文档,如果有多个文档,那么我们可以使用几种不同的方法\n","* Map Reduce \n","将所有块与问题一起传递给语言模型,获取回复,使用另一个语言模型调用将所有单独的回复总结成最终答案,它可以在任意数量的文档上运行。可以并行处理单个问题,同时也需要更多的调用。它将所有文档视为独立的\n","* Refine \n","用于循环许多文档,际上是迭代的,建立在先前文档的答案之上,非常适合前后因果信息并随时间逐步构建答案,依赖于先前调用的结果。它通常需要更长的时间,并且基本上需要与Map Reduce一样多的调用\n","* Map Re-rank \n","对每个文档进行单个语言模型调用,要求它返回一个分数,选择最高分,这依赖于语言模型知道分数应该是什么,需要告诉它,如果它与文档相关,则应该是高分,并在那里精细调整说明,可以批量处理它们相对较快,但是更加昂贵\n","* Stuff \n","将所有内容组合成一个文档"]}],"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.9.12"},"toc":{"base_numbering":1,"nav_menu":{},"number_sections":false,"sideBar":true,"skip_h1_title":false,"title_cell":"Table of Contents","title_sidebar":"Contents","toc_cell":false,"toc_position":{},"toc_section_display":true,"toc_window_display":true}},"nbformat":4,"nbformat_minor":5} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f200ba9a", + "metadata": {}, + "source": [ + "# 第五章 基于文档的问答\n", + "\n", + " - [一、设置OpenAI API Key](#一、设置OpenAI-API-Key)\n", + " - [一、导入embedding模型和向量存储组件](#一、导入embedding模型和向量存储组件)\n", + " - [1.1 创建向量存储](#1.1-创建向量存储)\n", + " - [1.2 使用语言模型与文档结合使用](#1.2-使用语言模型与文档结合使用)\n", + " - [二、 如何回答我们文档的相关问题](#二、-如何回答我们文档的相关问题)\n" + ] + }, + { + "cell_type": "markdown", + "id": "52824b89-532a-4e54-87e9-1410813cd39e", + "metadata": {}, + "source": [ + "常见的应用场景是使用大语言模型来构建一个能够回答关于给定文档和文档集合的问答系统。对于给定的文档, 比如从PDF、网页、公司主页中提取构建的内部文档集合,我们可以使用大语言模型来回答关于这些文档内容的问题,以帮助用户更有效地获取和使用他们所需要的信息。这种方式非常有效且灵活地适用于实际应用场景,因为它不仅仅利用大语言模型已有的训练集数据信息,它还能使用外部信息。\n", + "\n", + "这个过程,我们会涉及LongChain中的其他组件,比如:表征模型(Embedding Models)和向量储存(Vector Stores)" + ] + }, + { + "cell_type": "markdown", + "id": "42ccf132-cfab-4153-97b5-d545faae4d36", + "metadata": { + "tags": [] + }, + "source": [ + "## 一、设置OpenAI API Key" + ] + }, + { + "cell_type": "markdown", + "id": "83823216-ebf8-4554-9e8f-6d1b0c6878e7", + "metadata": {}, + "source": [ + "\n", + "登陆 [OpenAI 账户](https://platform.openai.com/account/api-keys) 获取API Key,然后将其设置为环境变量。\n", + "\n", + "- 如果你想要设置为全局环境变量,可以参考[知乎文章](https://zhuanlan.zhihu.com/p/627665725)。\n", + "- 如果你想要设置为本地/项目环境变量,在本文件目录下创建`.env`文件, 打开文件输入以下内容。\n", + "\n", + "

\n", + " OPENAI_API_KEY=\"your_api_key\" \n", + "

\n", + " \n", + " 替换\"your_api_key\"为你自己的 API Key" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "cc33ceb1-535f-454d-988c-347a8b14fd72", + "metadata": {}, + "outputs": [], + "source": [ + "# 下载需要的包python-dotenv和openai\n", + "# 如果你需要查看安装过程日志,可删除 -q \n", + "!pip install -q python-dotenv\n", + "!pip install -q openai" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e3c97235-f101-47f2-92db-1c37f4bf9845", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import os\n", + "import openai\n", + "from dotenv import load_dotenv, find_dotenv\n", + "\n", + "# 读取本地/项目的环境变量。\n", + "\n", + "# find_dotenv()寻找并定位.env文件的路径\n", + "# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中 \n", + "# 如果你设置的是全局的环境变量,这行代码则没有任何作用。\n", + "_ = load_dotenv(find_dotenv())\n", + "\n", + "# 获取环境变量 OPENAI_API_KEY\n", + "openai.api_key = os.environ['OPENAI_API_KEY'] " + ] + }, + { + "cell_type": "markdown", + "id": "8cb7a7ec", + "metadata": { + "height": 30 + }, + "source": [ + "## 一、直接" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6fbf1fe4-411a-4d22-b362-ac8400fa31b9", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install --upgrade -q langchain\n", + "!pip install -q docarray" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b", + "metadata": { + "height": 98 + }, + "outputs": [], + "source": [ + "from langchain.chains import RetrievalQA #检索QA链,在文档上进行检索\n", + "from langchain.chat_models import ChatOpenAI #openai模型\n", + "from langchain.document_loaders import CSVLoader #文档加载器,采用csv格式存储\n", + "from langchain.vectorstores import DocArrayInMemorySearch #向量存储\n", + "from IPython.display import display, Markdown #在jupyter显示信息的工具" + ] + }, + { + "cell_type": "markdown", + "id": "159206b6-46a8-47ee-99a8-13bf7d554da4", + "metadata": {}, + "source": [ + "### 1.1 导入数据" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7249846e", + "metadata": { + "height": 75 + }, + "outputs": [], + "source": [ + "file = 'data/OutdoorClothingCatalog_1000.csv'\n", + "loader = CSVLoader(file_path=file)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "7724f00e", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namedescription
0Women's Campside OxfordsThis ultracomfortable lace-to-toe Oxford boast...
1Recycled Waterhog Dog Mat, Chevron WeaveProtect your floors from spills and splashing ...
2Infant and Toddler Girls' Coastal Chill Swimsu...She'll love the bright colors, ruffles and exc...
3Refresh Swimwear, V-Neck Tankini ContrastsWhether you're going for a swim or heading out...
4EcoFlex 3L Storm PantsOur new TEK O2 technology makes our four-seaso...
\n", + "
" + ], + "text/plain": [ + " name \\\n", + "0 Women's Campside Oxfords \n", + "1 Recycled Waterhog Dog Mat, Chevron Weave \n", + "2 Infant and Toddler Girls' Coastal Chill Swimsu... \n", + "3 Refresh Swimwear, V-Neck Tankini Contrasts \n", + "4 EcoFlex 3L Storm Pants \n", + "\n", + " description \n", + "0 This ultracomfortable lace-to-toe Oxford boast... \n", + "1 Protect your floors from spills and splashing ... \n", + "2 She'll love the bright colors, ruffles and exc... \n", + "3 Whether you're going for a swim or heading out... \n", + "4 Our new TEK O2 technology makes our four-seaso... " + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#用Pandas导入并查看数据\n", + "import pandas as pd\n", + "\n", + "data = pd.read_csv(file,usecols=[1, 2])\n", + "data.head()" + ] + }, + { + "cell_type": "markdown", + "id": "3bd6422c", + "metadata": {}, + "source": [ + "提供了一个户外服装的CSV文件,我们将使用它与语言模型结合使用" + ] + }, + { + "cell_type": "markdown", + "id": "2963fc63", + "metadata": {}, + "source": [ + "### 1.2 基本文档加载器创建向量存储" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "5bfaba30", + "metadata": { + "height": 30 + }, + "outputs": [], + "source": [ + "from langchain.indexes import VectorstoreIndexCreator #导入向量存储索引创建器" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "9e200726", + "metadata": { + "height": 64 + }, + "outputs": [], + "source": [ + "# 创建指定向量存储类\n", + "# 创建完成后,从加载器中调用, 通过文档加载器列表加载\n", + "index = VectorstoreIndexCreator(vectorstore_cls=DocArrayInMemorySearch).from_loaders([loader])" + ] + }, + { + "cell_type": "markdown", + "id": "297216bf-ada7-498b-b448-7d98aadbfc27", + "metadata": {}, + "source": [ + "### 1.3 查询创建的向量存储" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "34562d81", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "query =\"Please list all your shirts with sun protection \\\n", + "in a table in markdown and summarize each one.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "cfd0cc37", + "metadata": { + "height": 30 + }, + "outputs": [], + "source": [ + "response = index.query(query)#使用索引查询创建一个响应,并传入这个查询" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "ae21f1ff", + "metadata": { + "height": 30, + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "\n", + "\n", + "| Name | Description |\n", + "| --- | --- |\n", + "| Men's Tropical Plaid Short-Sleeve Shirt | UPF 50+ rated, 100% polyester, wrinkle-resistant, front and back cape venting, two front bellows pockets |\n", + "| Men's Plaid Tropic Shirt, Short-Sleeve | UPF 50+ rated, 52% polyester and 48% nylon, machine washable and dryable, front and back cape venting, two front bellows pockets |\n", + "| Men's TropicVibe Shirt, Short-Sleeve | UPF 50+ rated, 71% Nylon, 29% Polyester, 100% Polyester knit mesh, wrinkle resistant, front and back cape venting, two front bellows pockets |\n", + "| Sun Shield Shirt by | UPF 50+ rated, 78% nylon, 22% Lycra Xtra Life fiber, wicks moisture, fits comfortably over swimsuit, abrasion resistant |\n", + "\n", + "All four shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. The Men's Tropical Plaid Short-Sleeve Shirt is made of 100% polyester and is wrinkle-resistant. The Men's Plaid Trop" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(Markdown(response))#查看查询返回的内容" + ] + }, + { + "cell_type": "markdown", + "id": "eb74cc79", + "metadata": {}, + "source": [ + "得到了一个Markdown表格,其中包含所有带有防晒衣的衬衫的名称和描述,还得到了一个语言模型提供的不错的小总结" + ] + }, + { + "cell_type": "markdown", + "id": "dd34e50e", + "metadata": {}, + "source": [ + "## 二、 结合表征模型和向量存储\n", + "\n", + "使用语言模型与文档结合使用时,语言模型一次只能使用几千个单词的信息。如果我们文档比较长,如何让语言模型回答关于其中所有内容的问题呢?我们通过几个通过向量表征(Embeddings)和向量存储(Vector Store)实现\n", + "\n", + "文本表征(Embeddings)是对文本语义的向量表征,相似内容的文本具有相似的表征向量。这使我们可以在向量空间中比较文本的相似性。\n", + "\n", + "向量数据库(Vector Database)用来存储文档的文本块。对于给定的文档,我们首先将其分成较小的文本块(chunks),然后获取每个小文本块的文本表征,并将这些表征储存在向量数据库中。这个流程正是创建索引(index)的过程。将文档分成小文本快的原因在于我们可能无法将整个文档传入语言模型进行处理。\n", + "\n", + "索引创建完成后,我们可以使用索引来查找与传入的查询(Query)最相关的文本片段 - 首先我们为查询获取向量表征,然后我们将其与向量数据库中的所有向量进行比较并选择最相似的n个文本块,最后我们将这些相似的文本块构建提示,并输入到语言模型,从而得到最终答案。" + ] + }, + { + "cell_type": "markdown", + "id": "20d9f53b-a4cd-44df-9ac1-8cba20db129f", + "metadata": {}, + "source": [ + "### 2.1 导入数据" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "631396c6", + "metadata": { + "height": 30 + }, + "outputs": [], + "source": [ + "#创建一个文档加载器,通过csv格式加载\n", + "loader = CSVLoader(file_path=file)\n", + "docs = loader.load()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4a977f44", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Document(page_content=\": 0\\nname: Women's Campside Oxfords\\ndescription: This ultracomfortable lace-to-toe Oxford boasts a super-soft canvas, thick cushioning, and quality construction for a broken-in feel from the first time you put them on. \\n\\nSize & Fit: Order regular shoe size. For half sizes not offered, order up to next whole size. \\n\\nSpecs: Approx. weight: 1 lb.1 oz. per pair. \\n\\nConstruction: Soft canvas material for a broken-in feel and look. Comfortable EVA innersole with Cleansport NXT® antimicrobial odor control. Vintage hunt, fish and camping motif on innersole. Moderate arch contour of innersole. EVA foam midsole for cushioning and support. Chain-tread-inspired molded rubber outsole with modified chain-tread pattern. Imported. \\n\\nQuestions? Please contact us for any inquiries.\", metadata={'source': 'data/OutdoorClothingCatalog_1000.csv', 'row': 0})" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#查看单个文档,每个文档对应于CSV中的一行数据\n", + "docs[0]" + ] + }, + { + "cell_type": "markdown", + "id": "2c975206-3ad1-41ad-af54-b51e3b6fdefc", + "metadata": {}, + "source": [ + "### 2.2 文本向量表征模型" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e875693a", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "#使用OpenAIEmbedding类\n", + "from langchain.embeddings import OpenAIEmbeddings \n", + "embeddings = OpenAIEmbeddings() #初始化" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "779bec75", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1536\n" + ] + } + ], + "source": [ + "#因为文档比较短了,所以这里不需要进行任何分块,可以直接进行向量表征\n", + "#使用初始化OpenAIEmbedding实例上的查询方法embed_query为文本创建向量表征\n", + "embed = embeddings.embed_query(\"Hi my name is Harrison\")\n", + "\n", + "#查看得到向量表征的长度\n", + "print(len(embed))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9d00d346", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-0.02194717898964882, 0.006735079921782017, -0.01816144771873951, -0.03916534036397934, -0.014086442068219185]\n" + ] + } + ], + "source": [ + "#每个元素都是不同的数字值,组合起来就是文本的向量表征\n", + "print(embed[:5])" + ] + }, + { + "cell_type": "markdown", + "id": "e60b3acd-a9ae-4085-a002-e6db3bf477f2", + "metadata": {}, + "source": [ + "### 2.3 基于向量表征创建向量存储" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "27ad0bb0", + "metadata": { + "height": 81 + }, + "outputs": [], + "source": [ + "# 将刚才创建文本向量表征(embeddings)存储在向量存储(vector store)中\n", + "# 使用DocArrayInMemorySearch类的from_documents方法来实现\n", + "# 该方法接受文档列表以及向量表征模型作为输入\n", + "db = DocArrayInMemorySearch.from_documents(docs, embeddings)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "13783b64-43ce-4e8d-8f97-ec4f07b15015", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.0.234'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import langchain\n", + "langchain.__version__" + ] + }, + { + "cell_type": "markdown", + "id": "36115eae-9b8e-4150-9604-8bfa6c071b2f", + "metadata": {}, + "source": [ + "### 2.4 查询创建的向量存储" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7909c6b7", + "metadata": { + "height": 30 + }, + "outputs": [], + "source": [ + "query = \"Please suggest a shirt with sunblocking\"\n", + "\n", + "#使用上面的向量存储来查找与传入查询类似的文本,得到一个相似文档列表\n", + "docs = db.similarity_search(query)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "43321853", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#打印返回文档的个数\n", + "len(docs)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "6eba90b5", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Document(page_content=': 255\\nname: Sun Shield Shirt by\\ndescription: \"Block the sun, not the fun – our high-performance sun shirt is guaranteed to protect from harmful UV rays. \\n\\nSize & Fit: Slightly Fitted: Softly shapes the body. Falls at hip.\\n\\nFabric & Care: 78% nylon, 22% Lycra Xtra Life fiber. UPF 50+ rated – the highest rated sun protection possible. Handwash, line dry.\\n\\nAdditional Features: Wicks moisture for quick-drying comfort. Fits comfortably over your favorite swimsuit. Abrasion resistant for season after season of wear. Imported.\\n\\nSun Protection That Won\\'t Wear Off\\nOur high-performance fabric provides SPF 50+ sun protection, blocking 98% of the sun\\'s harmful rays. This fabric is recommended by The Skin Cancer Foundation as an effective UV protectant.', metadata={'source': 'data/OutdoorClothingCatalog_1000.csv', 'row': 255})" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#打印返回的第一个文档\n", + "docs[0] " + ] + }, + { + "cell_type": "markdown", + "id": "566ee2d3-fa53-4138-8fa8-06e2c6fb8732", + "metadata": {}, + "source": [ + "我们可以看到一个返回了四个结果。输出的第一结果是一件关于防晒的衬衫,满足我们查询的要求:`请推荐一件防晒功能的衬衫(Please suggest a shirt with sunblocking)`" + ] + }, + { + "cell_type": "markdown", + "id": "fe41b36f", + "metadata": {}, + "source": [ + "### 2.5 使用向量储存回答文档的相关问题" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "c0c3596e", + "metadata": { + "height": 30 + }, + "outputs": [], + "source": [ + "#基于向量储存,创建检索器\n", + "retriever = db.as_retriever() " + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "0625f5e8", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "#导入大语言模型, 这里使用默认模型gpt-3.5-turbo会出现504服务器超时,因此使用gpt-3.5-turbo-0301\n", + "llm = ChatOpenAI(model_name=\"gpt-3.5-turbo-0301\",temperature = 0.0) " + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "a573f58a", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "#合并获得的相似文档内容\n", + "qdocs = \"\".join([docs[i].page_content for i in range(len(docs))]) " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "14682d95", + "metadata": { + "height": 64 + }, + "outputs": [], + "source": [ + "#将合并的相似文档内容后加上问题(question)输入到 `llm.call_as_llm`中\n", + "#这里问题是:以Markdown表格的方式列出所有具有防晒功能的衬衫并总结\n", + "response = llm.call_as_llm(f\"{qdocs} Question: Please list all your \\\n", + "shirts with sun protection in a table in markdown and summarize each one.\") " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "8bba545b", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "| Name | Description |\n", + "| --- | --- |\n", + "| Sun Shield Shirt | High-performance sun shirt with UPF 50+ sun protection, moisture-wicking, and abrasion-resistant fabric. Fits comfortably over swimsuits. |\n", + "| Men's Plaid Tropic Shirt | Ultracomfortable shirt with UPF 50+ sun protection, wrinkle-free fabric, and front/back cape venting. Made with 52% polyester and 48% nylon. |\n", + "| Men's TropicVibe Shirt | Men's sun-protection shirt with built-in UPF 50+ and wrinkle-resistant fabric. Features front/back cape venting and two front bellows pockets. |\n", + "| Men's Tropical Plaid Short-Sleeve Shirt | Lightest hot-weather shirt with UPF 50+ sun protection, relaxed traditional fit, and front/back cape venting. Made with 100% polyester. |\n", + "\n", + "All of these shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. They also have additional features such as moisture-wicking, wrinkle-resistant, and venting for cool breezes. The Sun Shield Shirt is abrasion-resistant and fits comfortably over swimsuits. The Men's Plaid Tropic Shirt is made with a blend of polyester and nylon and is machine washable/dryable. The Men's TropicVibe Shirt is also wrinkle-resistant and has two front bellows pockets. The Men's Tropical Plaid Short-Sleeve Shirt has a relaxed traditional fit and is made with 100% polyester." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(Markdown(response))" + ] + }, + { + "cell_type": "markdown", + "id": "12f042e7", + "metadata": {}, + "source": [ + "在此处打印响应,我们可以看到我们得到了一个表格,正如我们所要求的那样" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "32c94d22", + "metadata": { + "height": 115 + }, + "outputs": [], + "source": [ + "''' \n", + "通过LangChain链封装起来\n", + "创建一个检索QA链,对检索到的文档进行问题回答,要创建这样的链,我们将传入几个不同的东西\n", + "1、语言模型,在最后进行文本生成\n", + "2、传入链类型,这里使用stuff,将所有文档塞入上下文并对语言模型进行一次调用\n", + "3、传入一个检索器\n", + "'''\n", + "\n", + "\n", + "qa_stuff = RetrievalQA.from_chain_type(\n", + " llm=llm, \n", + " chain_type=\"stuff\", \n", + " retriever=retriever, \n", + " verbose=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "e4769316", + "metadata": { + "height": 47 + }, + "outputs": [], + "source": [ + "query = \"Please list all your shirts with sun protection in a table \\\n", + "in markdown and summarize each one.\"#创建一个查询并在此查询上运行链" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "1fc3c2f3", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new RetrievalQA chain...\u001b[0m\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [22]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[43mqa_stuff\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mquery\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:440\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, tags, metadata, *args, **kwargs)\u001b[0m\n\u001b[1;32m 438\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 439\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 440\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtags\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmetadata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmetadata\u001b[49m\u001b[43m)\u001b[49m[\n\u001b[1;32m 441\u001b[0m _output_key\n\u001b[1;32m 442\u001b[0m ]\n\u001b[1;32m 444\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks, tags\u001b[38;5;241m=\u001b[39mtags, metadata\u001b[38;5;241m=\u001b[39mmetadata)[\n\u001b[1;32m 446\u001b[0m _output_key\n\u001b[1;32m 447\u001b[0m ]\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:243\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 243\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 244\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 245\u001b[0m final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[1;32m 246\u001b[0m inputs, outputs, return_only_outputs\n\u001b[1;32m 247\u001b[0m )\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:237\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 231\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 232\u001b[0m dumpd(\u001b[38;5;28mself\u001b[39m),\n\u001b[1;32m 233\u001b[0m inputs,\n\u001b[1;32m 234\u001b[0m )\n\u001b[1;32m 235\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 236\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 237\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 240\u001b[0m )\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/retrieval_qa/base.py:131\u001b[0m, in \u001b[0;36mBaseRetrievalQA._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 130\u001b[0m docs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_docs(question) \u001b[38;5;66;03m# type: ignore[call-arg]\u001b[39;00m\n\u001b[0;32m--> 131\u001b[0m answer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcombine_documents_chain\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 132\u001b[0m \u001b[43m \u001b[49m\u001b[43minput_documents\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdocs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mquestion\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquestion\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_run_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 133\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreturn_source_documents:\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m {\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_key: answer, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msource_documents\u001b[39m\u001b[38;5;124m\"\u001b[39m: docs}\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:445\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, tags, metadata, *args, **kwargs)\u001b[0m\n\u001b[1;32m 440\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(args[\u001b[38;5;241m0\u001b[39m], callbacks\u001b[38;5;241m=\u001b[39mcallbacks, tags\u001b[38;5;241m=\u001b[39mtags, metadata\u001b[38;5;241m=\u001b[39mmetadata)[\n\u001b[1;32m 441\u001b[0m _output_key\n\u001b[1;32m 442\u001b[0m ]\n\u001b[1;32m 444\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[0;32m--> 445\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtags\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmetadata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmetadata\u001b[49m\u001b[43m)\u001b[49m[\n\u001b[1;32m 446\u001b[0m _output_key\n\u001b[1;32m 447\u001b[0m ]\n\u001b[1;32m 449\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 450\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 451\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supported with either positional arguments or keyword arguments,\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 452\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m but none were provided.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 453\u001b[0m )\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:243\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 243\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 244\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 245\u001b[0m final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[1;32m 246\u001b[0m inputs, outputs, return_only_outputs\n\u001b[1;32m 247\u001b[0m )\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:237\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 231\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 232\u001b[0m dumpd(\u001b[38;5;28mself\u001b[39m),\n\u001b[1;32m 233\u001b[0m inputs,\n\u001b[1;32m 234\u001b[0m )\n\u001b[1;32m 235\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 236\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 237\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 240\u001b[0m )\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/combine_documents/base.py:106\u001b[0m, in \u001b[0;36mBaseCombineDocumentsChain._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 104\u001b[0m \u001b[38;5;66;03m# Other keys are assumed to be needed for LLM prediction\u001b[39;00m\n\u001b[1;32m 105\u001b[0m other_keys \u001b[38;5;241m=\u001b[39m {k: v \u001b[38;5;28;01mfor\u001b[39;00m k, v \u001b[38;5;129;01min\u001b[39;00m inputs\u001b[38;5;241m.\u001b[39mitems() \u001b[38;5;28;01mif\u001b[39;00m k \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minput_key}\n\u001b[0;32m--> 106\u001b[0m output, extra_return_dict \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcombine_docs\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 107\u001b[0m \u001b[43m \u001b[49m\u001b[43mdocs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_run_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mother_keys\u001b[49m\n\u001b[1;32m 108\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 109\u001b[0m extra_return_dict[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_key] \u001b[38;5;241m=\u001b[39m output\n\u001b[1;32m 110\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m extra_return_dict\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/combine_documents/stuff.py:165\u001b[0m, in \u001b[0;36mStuffDocumentsChain.combine_docs\u001b[0;34m(self, docs, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 163\u001b[0m inputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_inputs(docs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 164\u001b[0m \u001b[38;5;66;03m# Call predict on the LLM.\u001b[39;00m\n\u001b[0;32m--> 165\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mllm_chain\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpredict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43minputs\u001b[49m\u001b[43m)\u001b[49m, {}\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/llm.py:252\u001b[0m, in \u001b[0;36mLLMChain.predict\u001b[0;34m(self, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 237\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpredict\u001b[39m(\u001b[38;5;28mself\u001b[39m, callbacks: Callbacks \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m:\n\u001b[1;32m 238\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Format prompt with kwargs and pass to LLM.\u001b[39;00m\n\u001b[1;32m 239\u001b[0m \n\u001b[1;32m 240\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 250\u001b[0m \u001b[38;5;124;03m completion = llm.predict(adjective=\"funny\")\u001b[39;00m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 252\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_key]\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:243\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 243\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 244\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 245\u001b[0m final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[1;32m 246\u001b[0m inputs, outputs, return_only_outputs\n\u001b[1;32m 247\u001b[0m )\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/base.py:237\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, include_run_info)\u001b[0m\n\u001b[1;32m 231\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 232\u001b[0m dumpd(\u001b[38;5;28mself\u001b[39m),\n\u001b[1;32m 233\u001b[0m inputs,\n\u001b[1;32m 234\u001b[0m )\n\u001b[1;32m 235\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 236\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 237\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 240\u001b[0m )\n\u001b[1;32m 241\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 242\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/llm.py:92\u001b[0m, in \u001b[0;36mLLMChain._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 87\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_call\u001b[39m(\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 89\u001b[0m inputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any],\n\u001b[1;32m 90\u001b[0m run_manager: Optional[CallbackManagerForChainRun] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 91\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Dict[\u001b[38;5;28mstr\u001b[39m, \u001b[38;5;28mstr\u001b[39m]:\n\u001b[0;32m---> 92\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgenerate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 93\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcreate_outputs(response)[\u001b[38;5;241m0\u001b[39m]\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chains/llm.py:102\u001b[0m, in \u001b[0;36mLLMChain.generate\u001b[0;34m(self, input_list, run_manager)\u001b[0m\n\u001b[1;32m 100\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Generate LLM result from inputs.\"\"\"\u001b[39;00m\n\u001b[1;32m 101\u001b[0m prompts, stop \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_prompts(input_list, run_manager\u001b[38;5;241m=\u001b[39mrun_manager)\n\u001b[0;32m--> 102\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mllm\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgenerate_prompt\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 103\u001b[0m \u001b[43m \u001b[49m\u001b[43mprompts\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 104\u001b[0m \u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 105\u001b[0m \u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 106\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mllm_kwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 107\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/base.py:230\u001b[0m, in \u001b[0;36mBaseChatModel.generate_prompt\u001b[0;34m(self, prompts, stop, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 222\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mgenerate_prompt\u001b[39m(\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 224\u001b[0m prompts: List[PromptValue],\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 227\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any,\n\u001b[1;32m 228\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m LLMResult:\n\u001b[1;32m 229\u001b[0m prompt_messages \u001b[38;5;241m=\u001b[39m [p\u001b[38;5;241m.\u001b[39mto_messages() \u001b[38;5;28;01mfor\u001b[39;00m p \u001b[38;5;129;01min\u001b[39;00m prompts]\n\u001b[0;32m--> 230\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgenerate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprompt_messages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/base.py:125\u001b[0m, in \u001b[0;36mBaseChatModel.generate\u001b[0;34m(self, messages, stop, callbacks, tags, metadata, **kwargs)\u001b[0m\n\u001b[1;32m 123\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m run_managers:\n\u001b[1;32m 124\u001b[0m run_managers[i]\u001b[38;5;241m.\u001b[39mon_llm_error(e)\n\u001b[0;32m--> 125\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 126\u001b[0m flattened_outputs \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 127\u001b[0m LLMResult(generations\u001b[38;5;241m=\u001b[39m[res\u001b[38;5;241m.\u001b[39mgenerations], llm_output\u001b[38;5;241m=\u001b[39mres\u001b[38;5;241m.\u001b[39mllm_output)\n\u001b[1;32m 128\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m res \u001b[38;5;129;01min\u001b[39;00m results\n\u001b[1;32m 129\u001b[0m ]\n\u001b[1;32m 130\u001b[0m llm_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_combine_llm_outputs([res\u001b[38;5;241m.\u001b[39mllm_output \u001b[38;5;28;01mfor\u001b[39;00m res \u001b[38;5;129;01min\u001b[39;00m results])\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/base.py:115\u001b[0m, in \u001b[0;36mBaseChatModel.generate\u001b[0;34m(self, messages, stop, callbacks, tags, metadata, **kwargs)\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(messages):\n\u001b[1;32m 113\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 114\u001b[0m results\u001b[38;5;241m.\u001b[39mappend(\n\u001b[0;32m--> 115\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_generate_with_cache\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 116\u001b[0m \u001b[43m \u001b[49m\u001b[43mm\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 117\u001b[0m \u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 118\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_managers\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_managers\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 119\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 120\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 121\u001b[0m )\n\u001b[1;32m 122\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 123\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m run_managers:\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/base.py:262\u001b[0m, in \u001b[0;36mBaseChatModel._generate_with_cache\u001b[0;34m(self, messages, stop, run_manager, **kwargs)\u001b[0m\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 259\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAsked to cache, but no cache found at `langchain.cache`.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 260\u001b[0m )\n\u001b[1;32m 261\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported:\n\u001b[0;32m--> 262\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_generate\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 263\u001b[0m \u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 264\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 265\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 266\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_generate(messages, stop\u001b[38;5;241m=\u001b[39mstop, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/openai.py:371\u001b[0m, in \u001b[0;36mChatOpenAI._generate\u001b[0;34m(self, messages, stop, run_manager, **kwargs)\u001b[0m\n\u001b[1;32m 363\u001b[0m message \u001b[38;5;241m=\u001b[39m _convert_dict_to_message(\n\u001b[1;32m 364\u001b[0m {\n\u001b[1;32m 365\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcontent\u001b[39m\u001b[38;5;124m\"\u001b[39m: inner_completion,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 368\u001b[0m }\n\u001b[1;32m 369\u001b[0m )\n\u001b[1;32m 370\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m ChatResult(generations\u001b[38;5;241m=\u001b[39m[ChatGeneration(message\u001b[38;5;241m=\u001b[39mmessage)])\n\u001b[0;32m--> 371\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcompletion_with_retry\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessages\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmessage_dicts\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 372\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_create_chat_result(response)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/openai.py:319\u001b[0m, in \u001b[0;36mChatOpenAI.completion_with_retry\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 315\u001b[0m \u001b[38;5;129m@retry_decorator\u001b[39m\n\u001b[1;32m 316\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_completion_with_retry\u001b[39m(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[1;32m 317\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclient\u001b[38;5;241m.\u001b[39mcreate(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m--> 319\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_completion_with_retry\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/tenacity/__init__.py:289\u001b[0m, in \u001b[0;36mBaseRetrying.wraps..wrapped_f\u001b[0;34m(*args, **kw)\u001b[0m\n\u001b[1;32m 287\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(f)\n\u001b[1;32m 288\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapped_f\u001b[39m(\u001b[38;5;241m*\u001b[39margs: t\u001b[38;5;241m.\u001b[39mAny, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkw: t\u001b[38;5;241m.\u001b[39mAny) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m t\u001b[38;5;241m.\u001b[39mAny:\n\u001b[0;32m--> 289\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkw\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/tenacity/__init__.py:379\u001b[0m, in \u001b[0;36mRetrying.__call__\u001b[0;34m(self, fn, *args, **kwargs)\u001b[0m\n\u001b[1;32m 377\u001b[0m retry_state \u001b[38;5;241m=\u001b[39m RetryCallState(retry_object\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m, fn\u001b[38;5;241m=\u001b[39mfn, args\u001b[38;5;241m=\u001b[39margs, kwargs\u001b[38;5;241m=\u001b[39mkwargs)\n\u001b[1;32m 378\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 379\u001b[0m do \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter\u001b[49m\u001b[43m(\u001b[49m\u001b[43mretry_state\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mretry_state\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 380\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(do, DoAttempt):\n\u001b[1;32m 381\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/tenacity/__init__.py:314\u001b[0m, in \u001b[0;36mBaseRetrying.iter\u001b[0;34m(self, retry_state)\u001b[0m\n\u001b[1;32m 312\u001b[0m is_explicit_retry \u001b[38;5;241m=\u001b[39m fut\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(fut\u001b[38;5;241m.\u001b[39mexception(), TryAgain)\n\u001b[1;32m 313\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (is_explicit_retry \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mretry(retry_state)):\n\u001b[0;32m--> 314\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfut\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresult\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 316\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mafter \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 317\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mafter(retry_state)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/concurrent/futures/_base.py:439\u001b[0m, in \u001b[0;36mFuture.result\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 437\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m CancelledError()\n\u001b[1;32m 438\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state \u001b[38;5;241m==\u001b[39m FINISHED:\n\u001b[0;32m--> 439\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__get_result\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 441\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_condition\u001b[38;5;241m.\u001b[39mwait(timeout)\n\u001b[1;32m 443\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state \u001b[38;5;129;01min\u001b[39;00m [CANCELLED, CANCELLED_AND_NOTIFIED]:\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/concurrent/futures/_base.py:391\u001b[0m, in \u001b[0;36mFuture.__get_result\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 389\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception:\n\u001b[1;32m 390\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 391\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception\n\u001b[1;32m 392\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 393\u001b[0m \u001b[38;5;66;03m# Break a reference cycle with the exception in self._exception\u001b[39;00m\n\u001b[1;32m 394\u001b[0m \u001b[38;5;28mself\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/tenacity/__init__.py:382\u001b[0m, in \u001b[0;36mRetrying.__call__\u001b[0;34m(self, fn, *args, **kwargs)\u001b[0m\n\u001b[1;32m 380\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(do, DoAttempt):\n\u001b[1;32m 381\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 382\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 383\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m: \u001b[38;5;66;03m# noqa: B902\u001b[39;00m\n\u001b[1;32m 384\u001b[0m retry_state\u001b[38;5;241m.\u001b[39mset_exception(sys\u001b[38;5;241m.\u001b[39mexc_info()) \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/langchain/chat_models/openai.py:317\u001b[0m, in \u001b[0;36mChatOpenAI.completion_with_retry.._completion_with_retry\u001b[0;34m(**kwargs)\u001b[0m\n\u001b[1;32m 315\u001b[0m \u001b[38;5;129m@retry_decorator\u001b[39m\n\u001b[1;32m 316\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_completion_with_retry\u001b[39m(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[0;32m--> 317\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/openai/api_resources/chat_completion.py:25\u001b[0m, in \u001b[0;36mChatCompletion.create\u001b[0;34m(cls, *args, **kwargs)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 25\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m TryAgain \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 27\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m timeout \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m time\u001b[38;5;241m.\u001b[39mtime() \u001b[38;5;241m>\u001b[39m start \u001b[38;5;241m+\u001b[39m timeout:\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/openai/api_resources/abstract/engine_api_resource.py:153\u001b[0m, in \u001b[0;36mEngineAPIResource.create\u001b[0;34m(cls, api_key, api_base, api_type, request_id, api_version, organization, **params)\u001b[0m\n\u001b[1;32m 127\u001b[0m \u001b[38;5;129m@classmethod\u001b[39m\n\u001b[1;32m 128\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcreate\u001b[39m(\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28mcls\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams,\n\u001b[1;32m 137\u001b[0m ):\n\u001b[1;32m 138\u001b[0m (\n\u001b[1;32m 139\u001b[0m deployment_id,\n\u001b[1;32m 140\u001b[0m engine,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 150\u001b[0m api_key, api_base, api_type, api_version, organization, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mparams\n\u001b[1;32m 151\u001b[0m )\n\u001b[0;32m--> 153\u001b[0m response, _, api_key \u001b[38;5;241m=\u001b[39m \u001b[43mrequestor\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 154\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mpost\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 155\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 156\u001b[0m \u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 157\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 158\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 159\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest_id\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 160\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest_timeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest_timeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 161\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m stream:\n\u001b[1;32m 164\u001b[0m \u001b[38;5;66;03m# must be an iterator\u001b[39;00m\n\u001b[1;32m 165\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(response, OpenAIResponse)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/openai/api_requestor.py:220\u001b[0m, in \u001b[0;36mAPIRequestor.request\u001b[0;34m(self, method, url, params, headers, files, stream, request_id, request_timeout)\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrequest\u001b[39m(\n\u001b[1;32m 210\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 211\u001b[0m method,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 218\u001b[0m request_timeout: Optional[Union[\u001b[38;5;28mfloat\u001b[39m, Tuple[\u001b[38;5;28mfloat\u001b[39m, \u001b[38;5;28mfloat\u001b[39m]]] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 219\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Tuple[Union[OpenAIResponse, Iterator[OpenAIResponse]], \u001b[38;5;28mbool\u001b[39m, \u001b[38;5;28mstr\u001b[39m]:\n\u001b[0;32m--> 220\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest_raw\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 221\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlower\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 222\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 223\u001b[0m \u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 224\u001b[0m \u001b[43m \u001b[49m\u001b[43msupplied_headers\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 225\u001b[0m \u001b[43m \u001b[49m\u001b[43mfiles\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfiles\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 226\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 227\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest_id\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 228\u001b[0m \u001b[43m \u001b[49m\u001b[43mrequest_timeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest_timeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 229\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 230\u001b[0m resp, got_stream \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_interpret_response(result, stream)\n\u001b[1;32m 231\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp, got_stream, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mapi_key\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/openai/api_requestor.py:520\u001b[0m, in \u001b[0;36mAPIRequestor.request_raw\u001b[0;34m(self, method, url, params, supplied_headers, files, stream, request_id, request_timeout)\u001b[0m\n\u001b[1;32m 518\u001b[0m _thread_context\u001b[38;5;241m.\u001b[39msession \u001b[38;5;241m=\u001b[39m _make_session()\n\u001b[1;32m 519\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 520\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43m_thread_context\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 521\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 522\u001b[0m \u001b[43m \u001b[49m\u001b[43mabs_url\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 523\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 524\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 525\u001b[0m \u001b[43m \u001b[49m\u001b[43mfiles\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfiles\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 526\u001b[0m \u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 527\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest_timeout\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrequest_timeout\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mTIMEOUT_SECS\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 528\u001b[0m \u001b[43m \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_thread_context\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 529\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 530\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m requests\u001b[38;5;241m.\u001b[39mexceptions\u001b[38;5;241m.\u001b[39mTimeout \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 531\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m error\u001b[38;5;241m.\u001b[39mTimeout(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRequest timed out: \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(e)) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01me\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/requests/sessions.py:529\u001b[0m, in \u001b[0;36mSession.request\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 524\u001b[0m send_kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 525\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtimeout\u001b[39m\u001b[38;5;124m'\u001b[39m: timeout,\n\u001b[1;32m 526\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mallow_redirects\u001b[39m\u001b[38;5;124m'\u001b[39m: allow_redirects,\n\u001b[1;32m 527\u001b[0m }\n\u001b[1;32m 528\u001b[0m send_kwargs\u001b[38;5;241m.\u001b[39mupdate(settings)\n\u001b[0;32m--> 529\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43msend_kwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 531\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/requests/sessions.py:645\u001b[0m, in \u001b[0;36mSession.send\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 642\u001b[0m start \u001b[38;5;241m=\u001b[39m preferred_clock()\n\u001b[1;32m 644\u001b[0m \u001b[38;5;66;03m# Send the request\u001b[39;00m\n\u001b[0;32m--> 645\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43madapter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 647\u001b[0m \u001b[38;5;66;03m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[1;32m 648\u001b[0m elapsed \u001b[38;5;241m=\u001b[39m preferred_clock() \u001b[38;5;241m-\u001b[39m start\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/requests/adapters.py:440\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 438\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 439\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m chunked:\n\u001b[0;32m--> 440\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43murlopen\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 441\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 442\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 443\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 444\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[43m \u001b[49m\u001b[43mredirect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 446\u001b[0m \u001b[43m \u001b[49m\u001b[43massert_same_host\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 447\u001b[0m \u001b[43m \u001b[49m\u001b[43mpreload_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 448\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecode_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 449\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m 451\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 453\u001b[0m \u001b[38;5;66;03m# Send the request.\u001b[39;00m\n\u001b[1;32m 454\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 455\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(conn, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mproxy_pool\u001b[39m\u001b[38;5;124m'\u001b[39m):\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/urllib3/connectionpool.py:703\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 700\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_prepare_proxy(conn)\n\u001b[1;32m 702\u001b[0m \u001b[38;5;66;03m# Make the request on the httplib connection object.\u001b[39;00m\n\u001b[0;32m--> 703\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_make_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 704\u001b[0m \u001b[43m \u001b[49m\u001b[43mconn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 706\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 707\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 708\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 709\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 710\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunked\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 711\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 713\u001b[0m \u001b[38;5;66;03m# If we're going to release the connection in ``finally:``, then\u001b[39;00m\n\u001b[1;32m 714\u001b[0m \u001b[38;5;66;03m# the response doesn't need to know about the connection. Otherwise\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[38;5;66;03m# it will also try to release it and we'll have a double-release\u001b[39;00m\n\u001b[1;32m 716\u001b[0m \u001b[38;5;66;03m# mess.\u001b[39;00m\n\u001b[1;32m 717\u001b[0m response_conn \u001b[38;5;241m=\u001b[39m conn \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m release_conn \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/urllib3/connectionpool.py:449\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mgetresponse()\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[0;32m--> 449\u001b[0m \u001b[43msix\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraise_from\u001b[49m\u001b[43m(\u001b[49m\u001b[43me\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m 450\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (SocketTimeout, BaseSSLError, SocketError) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 451\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_timeout(err\u001b[38;5;241m=\u001b[39me, url\u001b[38;5;241m=\u001b[39murl, timeout_value\u001b[38;5;241m=\u001b[39mread_timeout)\n", + "File \u001b[0;32m:3\u001b[0m, in \u001b[0;36mraise_from\u001b[0;34m(value, from_value)\u001b[0m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/site-packages/urllib3/connectionpool.py:444\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 441\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m:\n\u001b[1;32m 442\u001b[0m \u001b[38;5;66;03m# Python 3\u001b[39;00m\n\u001b[1;32m 443\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 444\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetresponse\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 445\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 446\u001b[0m \u001b[38;5;66;03m# Remove the TypeError from the exception chain in\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[38;5;66;03m# Python 3 (including for exceptions like SystemExit).\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[38;5;66;03m# Otherwise it looks like a bug in the code.\u001b[39;00m\n\u001b[1;32m 449\u001b[0m six\u001b[38;5;241m.\u001b[39mraise_from(e, \u001b[38;5;28;01mNone\u001b[39;00m)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/http/client.py:1377\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1375\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1376\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1377\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbegin\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1378\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m:\n\u001b[1;32m 1379\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/http/client.py:320\u001b[0m, in \u001b[0;36mHTTPResponse.begin\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;66;03m# read until we get a non-100 response\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 320\u001b[0m version, status, reason \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_read_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 321\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m status \u001b[38;5;241m!=\u001b[39m CONTINUE:\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/http/client.py:281\u001b[0m, in \u001b[0;36mHTTPResponse._read_status\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_read_status\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m--> 281\u001b[0m line \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreadline\u001b[49m\u001b[43m(\u001b[49m\u001b[43m_MAXLINE\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miso-8859-1\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(line) \u001b[38;5;241m>\u001b[39m _MAXLINE:\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m LineTooLong(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstatus line\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/socket.py:704\u001b[0m, in \u001b[0;36mSocketIO.readinto\u001b[0;34m(self, b)\u001b[0m\n\u001b[1;32m 702\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 703\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 704\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv_into\u001b[49m\u001b[43m(\u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m timeout:\n\u001b[1;32m 706\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_timeout_occurred \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/ssl.py:1241\u001b[0m, in \u001b[0;36mSSLSocket.recv_into\u001b[0;34m(self, buffer, nbytes, flags)\u001b[0m\n\u001b[1;32m 1237\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m flags \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1238\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 1239\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnon-zero flags not allowed in calls to recv_into() on \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 1240\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m)\n\u001b[0;32m-> 1241\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnbytes\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1242\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1243\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mrecv_into(buffer, nbytes, flags)\n", + "File \u001b[0;32m~/opt/miniconda3/lib/python3.9/ssl.py:1099\u001b[0m, in \u001b[0;36mSSLSocket.read\u001b[0;34m(self, len, buffer)\u001b[0m\n\u001b[1;32m 1097\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1098\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m buffer \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 1099\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sslobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1100\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1101\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sslobj\u001b[38;5;241m.\u001b[39mread(\u001b[38;5;28mlen\u001b[39m)\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "response = qa_stuff.run(query)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "fba1a5db", + "metadata": { + "height": 30 + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "\n", + "\n", + "| Name | Description |\n", + "| --- | --- |\n", + "| Men's Tropical Plaid Short-Sleeve Shirt | UPF 50+ rated, 100% polyester, wrinkle-resistant, front and back cape venting, two front bellows pockets |\n", + "| Men's Plaid Tropic Shirt, Short-Sleeve | UPF 50+ rated, 52% polyester and 48% nylon, machine washable and dryable, front and back cape venting, two front bellows pockets |\n", + "| Men's TropicVibe Shirt, Short-Sleeve | UPF 50+ rated, 71% Nylon, 29% Polyester, 100% Polyester knit mesh, machine wash and dry, front and back cape venting, two front bellows pockets |\n", + "| Sun Shield Shirt by | UPF 50+ rated, 78% nylon, 22% Lycra Xtra Life fiber, handwash, line dry, wicks moisture, fits comfortably over swimsuit, abrasion resistant |\n", + "\n", + "All four shirts provide UPF 50+ sun protection, blocking 98% of the sun's harmful rays. The Men's Tropical Plaid Short-Sleeve Shirt is made of 100% polyester and is wrinkle-resistant" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(Markdown(response))#使用 display 和 markdown 显示它" + ] + }, + { + "cell_type": "markdown", + "id": "e28c5657", + "metadata": {}, + "source": [ + "这两个方式返回相同的结果" + ] + }, + { + "cell_type": "markdown", + "id": "44f1fa38", + "metadata": {}, + "source": [ + "想在许多不同类型的块上执行相同类型的问答,该怎么办?之前的实验中只返回了4个文档,如果有多个文档,那么我们可以使用几种不同的方法\n", + "* Map Reduce \n", + "将所有块与问题一起传递给语言模型,获取回复,使用另一个语言模型调用将所有单独的回复总结成最终答案,它可以在任意数量的文档上运行。可以并行处理单个问题,同时也需要更多的调用。它将所有文档视为独立的\n", + "* Refine \n", + "用于循环许多文档,际上是迭代的,建立在先前文档的答案之上,非常适合前后因果信息并随时间逐步构建答案,依赖于先前调用的结果。它通常需要更长的时间,并且基本上需要与Map Reduce一样多的调用\n", + "* Map Re-rank \n", + "对每个文档进行单个语言模型调用,要求它返回一个分数,选择最高分,这依赖于语言模型知道分数应该是什么,需要告诉它,如果它与文档相关,则应该是高分,并在那里精细调整说明,可以批量处理它们相对较快,但是更加昂贵\n", + "* Stuff \n", + "将所有内容组合成一个文档" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}