├── .gitignore ├── .npmrc ├── 101-prompt-engineering └── src │ ├── index.html │ ├── package.json │ ├── slides.md │ └── styles │ └── index.ts ├── 102-openai-api └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 103-prompt-landscape └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 201-langchain-modules └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 202-langchain-chains └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 203-langchain-agents └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 240106-langchain-status └── src │ ├── package.json │ └── slides.md ├── 240720-langchain-minio └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 301-langchain-chatdoc └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── 302-langserve └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── README.md ├── addons └── webup │ ├── .npmignore │ ├── components │ ├── B.vue │ ├── NPM.vue │ ├── PB.vue │ ├── T.vue │ ├── Val.vue │ ├── Version.vue │ └── Wiki.vue │ └── package.json ├── langchain-biweekly └── src │ ├── index.html │ ├── package.json │ └── slides.md ├── netlify.toml ├── package.json ├── pages ├── common │ ├── end.md │ ├── refs.md │ ├── series.md │ └── toc.md └── playground │ ├── langchain.md │ └── openai.md ├── pdfs ├── 101-prompt-engineering.pdf ├── 102-openai-api.pdf ├── 201-langchain-modules.pdf ├── 202-langchain-chains.pdf ├── 203-langchain-agents.pdf ├── 240106-langchain-status.pdf ├── 240720-langchain-minio.pdf ├── 302-langserve.pdf └── langchain-biweekly.pdf ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── styles ├── component.css └── layout.css ├── svgs ├── langchain-js-auto-docstrings.svg ├── langchain-js-runnable-chain.svg ├── langchain-modules.svg ├── langchain-parent-document-retriever.svg ├── langchain-use-cases.svg └── langsmith-modules.svg └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .history 124 | .vscode* 125 | 126 | # yarn v2 127 | .yarn/cache 128 | .yarn/unplugged 129 | .yarn/build-state.yml 130 | .yarn/install-state.gz 131 | .pnp.* 132 | 133 | # Local Netlify folder 134 | .netlify 135 | .vercel 136 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | ignore-workspace-root-check=true 3 | strict-peer-dependencies=false -------------------------------------------------------------------------------- /101-prompt-engineering/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /101-prompt-engineering/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /101-prompt-engineering/ --out ../../dist/101-prompt-engineering", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/101-prompt-engineering.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.42.4", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /101-prompt-engineering/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/101-prompt-engineering.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # AGI 提示工程指北 33 | 34 | Prompt Engineering in Action 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 |
43 | 45 | 46 | 47 | 49 | 50 | 51 | 53 | 54 | 55 |
56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | src: ../../pages/common/toc.md 63 | --- 64 | 65 | --- 66 | layout: two-cols 67 | title: 基础 LLM vs. 指令微调 LLM 68 | --- 69 | 70 | # 基础 LLM 71 | 72 | Base LLM 73 | 74 | - 模型行为:预测下一个(系列)单词 75 | - 训练内容:互联网和其它来源的大量数据 76 | 77 | ```md {2-} 78 | Once upon a time, there was a unicorn 79 | that lived in a magical forest with all her friends 80 | ``` 81 | 82 | > 基础 LLM 的默认行为是 “续写” 文本 83 | 84 |
85 | 86 | ```md {2-} 87 | What is the capital of France? 88 | What is France's largest city? 89 | What is France's population? 90 | What is the currency of France? 91 | ``` 92 | 93 | > 训练数据(比如互联网上的文章)很可能是关于法国的问答列表 94 | 95 | ::right:: 96 | 97 | # 指令微调 LLM 98 | 99 | Instruction Tuned LLM 100 | 101 | - 模型行为:接收指令,输出预测结果 102 | - 训练过程: 103 | - 从大量文本数据中训练出一个基础 LLM 104 | - 使用指令和良好尝试的输入输出进行微调和优化 105 | - 使用“[人类反馈强化学习](https://huggingface.co/blog/rlhf)”的技术进行进一步细化 106 | 107 | ```md {2-} 108 | What is the capital of France? 109 | The capital of France is Paris. 110 | ``` 111 | 112 | 💡 现在互联网上大家使用到的 LLM 基本都是这类模型 113 | 114 | --- 115 | layout: two-cols 116 | --- 117 | 118 | # 提示工程关键原则 119 | 120 | Principles of Prompting 121 | 122 | 原则一:编写清晰而具体的指令 123 | 124 | - 策略1⃣️:使用分隔符清楚地限定输入的不同部分 125 | - 策略2⃣️:要求模型结构化输出 126 | - 策略3⃣️:要求模型检查是否满足条件 127 | - 策略4⃣️:提供 少样本提示(Few Shot) 128 | 129 | 原则二:给模型充足的思考时间 130 | 131 | - 策略5⃣️:指定完成任务所需要的步骤 132 | - 策略6⃣️:指导模型制定自己的解决方法 133 | 134 | ::right:: 135 | 136 | # 模型的局限性 137 | 138 | Model Limitations 139 | 140 | 可能会产生 幻觉(Hallucination) 141 | 142 | - 不清楚自己的知识边界 143 | - 虚构听起来很有道理但实际伤感不正确的东西 144 | 145 | 减少幻觉的策略 146 | 147 | - 要求模型首先从文本中找到任何相关的引文 148 | - 然后要它使用那些引文来回答问题 149 | - 并将答案追溯回源文件 150 | 151 | --- 152 | src: ../../pages/playground/openai.md 153 | hideInToc: true 154 | --- 155 | 156 | --- 157 | level: 2 158 | --- 159 | 160 | # 策略一:使用分隔符清楚地限定输入的不同部分 161 | 162 | 常见的分隔符可以是:```,`""`,`<>`,`` 等 163 | 164 | - 输入里面可能包含其他指令,会覆盖掉你的指令 165 | - 可以使用任何明显的标点符号将特定的文本部分与提示的其余部分分开 166 | 167 | 168 | 169 | --- 170 | level: 2 171 | --- 172 | 173 | # 策略二:要求一个结构化的输出 174 | 175 | 常见的结构化输出可以是 JSON、HTML 等格式 176 | 177 | 在以下示例中,我们要求 GPT 生成三本书的标题、作者和类别,并要求以 JSON 的格式返回给我们。 178 | 179 | 180 | 181 | --- 182 | level: 2 183 | --- 184 | 185 | # 策略三:要求模型检查是否满足条件 186 | 187 | 如果任务做出的假设不一定满足,我们可以告诉模型先检查这些假设,如果不满足,指示并停止执行 188 | 189 | 在如下示例中,我们将给模型一段没有明确步骤的文本。模型在判断后应回答未提供步骤。 190 | 191 | 192 | 193 | --- 194 | level: 2 195 | --- 196 | 197 | # 策略三:要求模型检查是否满足条件(提供出路) 198 | 199 | 如果模型无法完成分配的任务,有时为模型提供备用路径可能会有所帮助。 200 | 201 |
202 | 203 | 204 | 205 | --- 206 | level: 2 207 | --- 208 | 209 | # 策略四:提供少量示例 210 | 211 | 即在要求模型执行实际任务之前,提供给它少量成功执行任务的示例 212 | 213 | 在如下示例中,我们要求模型以一致的风格作答;由于已经有了少量示例,它将以类似的语气回答。 214 | 215 | 216 | 217 | --- 218 | level: 2 219 | --- 220 | 221 | # 策略五:指定完成任务所需的步骤 222 | 223 | 接下来我们将通过给定一个复杂任务,给出完成该任务的一系列步骤,来展示这一策略的效果 224 | 225 | 首先我们描述了杰克和吉尔的故事,并给出一个指令。由于提示不充分,输出的内容带了不需要的序号。 226 | 227 | 228 | 229 | --- 230 | level: 2 231 | --- 232 | 233 | # 策略五:指定完成任务所需的步骤(续) 234 | 235 | 我们给出一个更好的 Prompt,该 Prompt 指定了输出的格式 236 | 237 | 238 | 239 | --- 240 | level: 2 241 | --- 242 | 243 | # 策略六:指导模型在下结论前找出自己的解法 244 | 245 | 有时候,明确地指导模型在做决策之前要思考解决方案,我们会得到更好的结果 246 | 247 | 在如下示例中,我们给出一个问题和一个学生的错误解答,要求模型判断解答是否正确。 248 | 249 | 250 | 251 | --- 252 | level: 2 253 | --- 254 | 255 | # 策略六:指导模型在下结论前找出自己的解法(续) 256 | 257 | 我们可以通过指导模型先自行找出一个解法来解决这个问题。通过明确步骤,让模型有更多时间思考 258 | 259 | 260 | 261 | --- 262 | 263 | # 提示工程需要迭代 264 | 265 | 当使用 LLM 构建应用程序时,很少在第一次尝试中就成功使用最终应用程序中所需的提示词 266 | 267 | 我们将以从产品说明书中生成营销文案这一示例,展示一些框架,以提示你思考如何迭代地分析和完善提示词。 268 | 269 | 270 | 271 | --- 272 | level: 2 273 | --- 274 | 275 | # 问题一:生成文本太长 276 | 277 | 解决方法:要求模型限制生成文本长度 278 | 279 | 因为它太长了,所以我会澄清我的提示,并说最多使用 50 个字。 280 | 281 | 282 | 283 | --- 284 | level: 2 285 | --- 286 | 287 | # 问题二:文本关注在错误的细节上 288 | 289 | 解决方法:要求模型专注于与目标受众相关的方面 290 | 291 | 修改提示让它更精确地描述椅子的技术细节,并要求在描述的结尾包括对应的 7 个字符产品 ID。 292 | 293 | 294 | 295 | --- 296 | level: 2 297 | --- 298 | 299 | # 问题三:需要一个更好的呈现形式 300 | 301 | 解决方法:要求模型抽取信息并组织成表格,并指定表格的列、表名和格式(如 HTML) 302 | 303 | 304 | 305 | --- 306 | layout: quote 307 | hideInToc: true 308 | --- 309 | 310 | # 大语言模型能力概览 311 | 312 | 概括(Summerize)、推断(Infer)、转换(Transform)、扩展(Expand) 313 | 314 | --- 315 | 316 | # 模型能力:概括(Summerize) 317 | 318 | 子能力:限制输出长度,侧重关键角度,提取关键信息 319 | 320 | 如果我们只想要提取某一角度的信息,并过滤掉其他所有信息,可以要求模型进行文本提取(Extract)。 321 | 322 | 323 | 324 | --- 325 | 326 | # 模型能力:推断(Infer)· 情绪 327 | 328 | 大语言模型可以从一段文本中提取正面或负面情感 329 | 330 | 在如下示例中,我们要求模型对一份客户反馈进行情绪推断,并抽取相关信息后进行格式化输出。 331 | 332 | 333 | 334 | --- 335 | 336 | # 模型能力:推断(Infer)· 主题 337 | 338 | 大语言模型也可以推断一段文本是关于什么的、有什么话题 339 | 340 | 在如下示例中,我们要求模型从一片虚构的文章中推断出其中的五个主题。 341 | 342 | 343 | 344 | --- 345 | 346 | # 模型能力:推断(Infer)· 分类 347 | 348 | 基于对于主题的推断,大语言模型还可以帮忙把主题和给定的分类进行映射 349 | 350 | 351 | 352 | --- 353 | 354 | # 模型能力:转换(Transform) 355 | 356 | 大语言模型非常擅长将输入转换成不同的格式,如多语种文本翻译、拼写及语法纠正、语气调整、格式转换等 357 | 358 | 如下的示例展示了一个综合样例,包括了文本翻译、拼写纠正、风格调整和格式转换。 359 | 360 | 361 | 362 | --- 363 | 364 | # 模型能力:扩展(Expand) 365 | 366 | 扩展是将短文本,例如一组说明或主题列表,输入给大型语言模型,让它生成更长的文本 367 | 368 | 如下示例中,我们将根据客户评价和对应的情感,要求模型撰写自定义电子邮件响应。 369 | 370 | 371 | 372 | --- 373 | src: ../../pages/common/refs.md 374 | --- 375 | 376 | --- 377 | src: ../../pages/common/end.md 378 | --- -------------------------------------------------------------------------------- /101-prompt-engineering/src/styles/index.ts: -------------------------------------------------------------------------------- 1 | import '../../../styles/layout.css'; 2 | import '../../../styles/component.css'; 3 | -------------------------------------------------------------------------------- /102-openai-api/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /102-openai-api/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /102-openai-api/ --out ../../dist/102-openai-api", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/102-openai-api.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.42.4", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /102-openai-api/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/102-openai-api.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # OpenAI API 浅出 33 | 34 | OpenAI API Walkthrough 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | src: ../../pages/common/toc.md 63 | --- 64 | 65 | --- 66 | layout: iframe 67 | url: https://www.youtube.com/embed/RQgBnQUaKG0?start=44 68 | hideInToc: true 69 | --- 70 | 71 | --- 72 | 73 | # 说到 OpenAI 会想到什么? 74 | 75 | 大家是否还记得当年 GitHub Copilot 的惊艳亮相,它背后的开发团队就是 OpenAI 76 | 77 | ###### OpenAI 实验室 / 公司 78 | 79 | - OpenAI 是一家美国的人工智能研究实验室,它由两部分组成: 80 | - 非营利性的 OpenAI Incorporated 81 | - 营利性子公司 OpenAI Limited Partnership 82 | - OpenAI 开展人工智能研究,其宣称的目的是促进和发展友好的人工智能 83 | 84 |
85 | 86 | ###### ChatGPT 聊天机器人 87 | 88 | - ChatGPT 是由 OpenAI 开发的人工智能聊天机器人应用,于 2022 年 11 月 30 日推出 89 | - 它的显着特点是使用户能够改进和引导对话达到所需的长度、格式、风格、细节级别和使用的语言 90 | 91 |
92 | 93 | ###### GPT-3/4 大语言模型 94 | 95 | - GPT-3 是由 OpenAI 在 2020 年推出的 大语言模型,是 ChatGPT 使用的默认模型 96 | - GPT-4 是由 OpenAI 在 2023 年 3 月 推出的 多模态 大语言模型 97 | 98 | --- 99 | src: ../../pages/playground/openai.md 100 | hideInToc: true 101 | --- 102 | 103 | --- 104 | layout: quote 105 | hideInToc: true 106 | --- 107 | 108 | # OpenAI API 概览 109 | 110 | Chat Completions,Completions,Embeddings,Moderations 111 | 112 | --- 113 | 114 | # 对话补全 API:Chat Completions 115 | 116 | ChatGPT(及高仿)对话机器人应用的基石 117 | 118 | 一段对话的一组消息文本; 模型推测的下一条对话内容 119 | 120 | ```ts {all|14-20} 121 | import { Configuration, OpenAIApi } from 'openai'; 122 | 123 | export const chat = async (prompt = "Hello world", options = {}) => { 124 | // Initialize OpenAI API stub 125 | const configuration = new Configuration({ 126 | apiKey: process.env.OPENAI, 127 | }); 128 | const openai = new OpenAIApi(configuration); 129 | 130 | // Prepare the messages 131 | const messages = typeof prompt === "string" 132 | ? [{ role: "user", content: prompt }] : prompt; 133 | 134 | // Request chat completion 135 | const chatCompletion = await openai.createChatCompletion({ 136 | model: "gpt-3.5-turbo", 137 | messages, 138 | ...options, 139 | }); 140 | return chatCompletion.data.choices[0].message.content; 141 | }; 142 | ``` 143 | 144 | --- 145 | level: 2 146 | --- 147 | 148 | # Chat Completions API 的常用参数 149 | 150 | 请访问 [官方文档](https://platform.openai.com/docs/api-reference/chat/create) 了解完整的参数;最新发布的 Functions Call 功能详见 后续章节 151 | 152 | ###### Required 153 | 154 | - `model`:目前的可用模型包括 GPT-3.5 和 GPT-4 的一些模型 155 | - `gpt-3.5-turbo`, `gpt-3.5-turbo-0613`, `gpt-3.5-turbo-16k`, `gpt-3.5-turbo-16k-0613` 156 | - `gpt-4`, `gpt-4-0613`, `gpt-4-32k`, `gpt-4-32k-0613` 157 | - `messages`:用于描述对话的具体内容,每条消息一般包含以下两个字段 158 | - `role`:三种角色 `system`(“对话语境架构师”), `user`(“我”), `assistant`(“对话机器人”) 159 | - `content`:消息的内容,也可以理解成是各个角色说的话 160 | 161 | 162 |
163 | 164 | ###### Optional 165 | 166 | - `temperature`:采样温度,介于(且包含) `0` 和 `2` 之间,默认为 `1`,温度越高输出越随机 167 | - `top_p`:从一组累计概率不超过 P 的词中选择(避免概率很低的词被选中),一般和“温度”二选一使用 168 | - `max_tokens`:所生成的内容的最多可以承载多少 Token;输入 + 输出 Token ≤ 模型的 Token 限量 169 | 170 | --- 171 | level: 3 172 | --- 173 | 174 | # Token 是怎么计算的? 175 | 176 | GPT 系列模型使用 Token 处理文本,模型了解这些 Token 之间的统计关系,并擅长生成序列中的下一个 Token 177 | 178 | ###### Token 的切分 179 | 180 | - 对于英文输入,一个 Token 一般对应 4 个字符或者四分之三个单词 181 | - 对于中文输入,一个 Token 一般对应一个或半个词 182 | 183 |
184 | 185 | ###### Token 的计算 186 | 187 | - OpenAI 提供了一个计算和可视化 Token 的 [页面](https://platform.openai.com/tokenizer) 188 | - 官方 Python 类库: [openai/tiktoken: tiktoken is a fast BPE tokeniser for use with OpenAI's models.](https://github.com/openai/tiktoken) 189 | - 社区 JavaScript 类库:[latitudegames/GPT-3-Encoder: JavaScript BPE Encoder Decoder for GPT-2 / GPT-3](https://github.com/latitudegames/GPT-3-Encoder) 190 | 191 |
192 | 193 | ###### Token 的用量([计费](https://openai.com/pricing#language-models)) 194 | 195 | - 不同模型有不同的 Token 限制,Token 限制是输入的 Prompt 和输出的 Completion 的 Token 数量之和 196 | - 因此输入的 Prompt 越长,能输出的 Completion 的上限就越低 197 | - `gpt-3.5-turbo` 的 Token 上限是 `4k`;`gpt-3.5-turbo-16k` 的上限是 `16k` 198 | 199 | --- 200 | level: 3 201 | --- 202 | 203 | # 关于 Token 切分的迷思 204 | 205 | 以英文为例,怎么理解 “一个 Token 一般对应 4 个字符或者四分之三个单词”;参见 [更多示例](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) 206 | 207 |
208 | 209 | 210 | 211 | --- 212 | level: 2 213 | --- 214 | 215 | # 幕后的游戏规则制定者:`role:system` 216 | 217 | OpenAI Playground 的默认系统提示是 “You are a helpful assistant” 218 | 219 | `system` 信息用于制定模型的规则,例如设定、回答准则一类的,目前只能通过 API 来进行设置。 220 | 221 | 222 | 223 | 224 | --- 225 | level: 3 226 | --- 227 | 228 | # 🌰 高阶版的 `system` 提示工程示例 229 | 230 | [LangGPT](https://github.com/yzfly/LangGPT): Empowering everyone to become a prompt expert!🚀 Structured Prompt,结构化提示词 231 | 232 | 233 | 234 | 💡 参考:[‌‌⁢‍⁢⁡⁢⁡⁡‌⁤群友 Arthur 等整理的 Prompt 最佳实践](https://ywh1bkansf.feishu.cn/wiki/JTjPweIUWiXjppkKGBwcu6QsnGd),[如何写好 Prompt: 结构化](https://www.lijigang.com/posts/chatgpt-prompt-structure/) 235 | 236 | --- 237 | 238 | # 文本补全 API:Completions 239 | 240 | 常用于给定主题的文章编写、代码片段的解读 241 | 242 | 一条或一组提示文本; 根据提示和参数推测的输出内容 243 | 244 | ```ts {all|10-15} 245 | import { Configuration, OpenAIApi } from 'openai'; 246 | 247 | export const complete = async (prompt, options = {}) => { 248 | // Initialize OpenAI API stub 249 | const configuration = new Configuration({ 250 | apiKey: process.env.OPENAI, 251 | }); 252 | const openai = new OpenAIApi(configuration); 253 | 254 | // Request completion 255 | const completion = await openai.createCompletion({ 256 | model: "text-davinci-003", 257 | prompt, 258 | ...options, 259 | }); 260 | return completion.data.choices[0].message.content; 261 | }; 262 | ``` 263 | 264 | --- 265 | level: 2 266 | --- 267 | 268 | # Completions API 的常用参数 269 | 270 | 请访问 [官方文档](https://platform.openai.com/docs/api-reference/completions) 了解完整的参数;该接口及其模型 [逐步退役](https://openai.com/blog/gpt-4-api-general-availability) 中 271 | 272 | ###### Required 273 | 274 | - `model`:目前的可用模型包括 GPT-3 的一些模型 275 | - `text-davinci-003`(最强), `text-davinci-002` 276 | - `text-curie-001`, `text-babbage-001`, `text-ada-001`(最快最便宜) 277 | - `prompt`:编码为字符串、字符串数组、Token 一维或者二维数组 278 | - 注意 `<|endoftext|>` 是模型在训练期间看到的文档分隔符 279 | - 因此如果在提示中没有另外指定分隔符,模型将像从新文档开始一样生成 280 | 281 |
282 | 283 | ###### Optional 284 | 285 | 基本和 Chat Completions 接口所用参数一致 286 | 287 | --- 288 | level: 2 289 | --- 290 | 291 | # 🌰 基于 Completions 的代码解读示例 292 | 293 | 294 | 295 | --- 296 | 297 | # 文本向量 API:Embeddings 298 | 299 | 面向文本问答、文本检索这类功能的基石;可访问 [官方文档](https://platform.openai.com/docs/api-reference/embeddings) 了解完整参数 300 | 301 | 一条或一组文本; 文本或 Token 对应的向量数组表达 302 | 303 | ```ts {all|10-12} 304 | import { Configuration, OpenAIApi } from 'openai'; 305 | 306 | export const embed = async (input, model = "text-embedding-ada-002") => { 307 | // Initialize OpenAI API stub 308 | const configuration = new Configuration({ 309 | apiKey: process.env.OPENAI, 310 | }); 311 | const openai = new OpenAIApi(configuration); 312 | 313 | // Request embedding 314 | const { data } = await openai.createEmbedding({ model, input }); 315 | return data.embedding; 316 | }; 317 | ``` 318 | 319 | ###### Required 320 | 321 | - `model`:`text-embedding-ada-002`, `text-search-ada-doc-001` 322 | - `input`:输入要 Embed 的文本,编码为字符串或 Token 数组 323 | - 要在单个请求中嵌入多个输入,可传递字符串数组或二维 Token 数组 324 | 325 | 326 | --- 327 | level: 2 328 | --- 329 | 330 | # Embeddings 如何用于文本问答 331 | 332 | 这部分内容会在 201 LangChain Components 分享中详细介绍 333 | 334 | ![Pinecone](https://s2.loli.net/2023/07/29/G6pqxYQcNK7tPJo.webp) 335 | 336 | 337 | --- 338 | 339 | # 文本审查 API:Moderations 340 | 341 | 识别和过滤各种类别的违禁内容,例如仇恨、自残、色情和暴力等;可访问 [官方文档](https://platform.openai.com/docs/api-reference/moderations) 了解完整参数 342 | 343 | 一条或一组文本; OpenAI [监督标准](https://platform.openai.com/docs/guides/moderation) 评分 344 | 345 | ```ts {all|10-12} 346 | import { Configuration, OpenAIApi } from 'openai'; 347 | 348 | export const moderate = async (input, model) => { 349 | // Initialize OpenAI API stub 350 | const configuration = new Configuration({ 351 | apiKey: process.env.OPENAI, 352 | }); 353 | const openai = new OpenAIApi(configuration); 354 | 355 | // Request moderation 356 | const { results } = await openai.createModeration({ model, input }); 357 | return results; 358 | }; 359 | ``` 360 | 361 | ###### Required 362 | 363 | - `input`:待检验的文本 364 | 365 | ###### Optional 366 | 367 | - `model`: `text-moderation-stable` 和 `text-moderation-latest`(默认,自更新) 368 | 369 | --- 370 | level: 2 371 | --- 372 | 373 | # 🌰 一个非常简单的文本内容审核的示例 374 | 375 |
376 | 377 | 378 | 379 | --- 380 | layout: quote 381 | hideInToc: true 382 | --- 383 | 384 | # 函数调用(Function Calling) 385 | 386 | Chat Completions 的新神器 🚀 387 | 388 | --- 389 | title: Chat Completions 神器:Function Calling 390 | --- 391 | 392 | # 函数调用的点睛之处 393 | 394 | 并非直接调用函数,而是告诉你应该怎么调用函数(包括用什么参数) 395 | 396 | ⛓️ 函数调度的基本流程: 397 | 398 | 1. 使用 Chat Completions 接口请求参数中定义的一组函数来调用模型(参见 [定义格式](https://platform.openai.com/docs/api-reference/chat/create#chat/create-functions)) 399 | 2. 模型可以选择调用函数 —— 输出一个符合用户自定义模式的字符串化 JSON 对象 400 | - 注意:模型可能会生成无效的 JSON 或幻觉参数 401 | - 幻觉参数输出通常可以通过系统消息来缓解,例如请尝试使用系统消息:“仅使用已经提供的函数” 402 | 3. 【可选】用户可以将字符串解析为代码中的 JSON,并使用提供的参数调用实际的函数(如果它们确实存在) 403 | 4. 【可选】将实际的函数的响应作为新的输入消息再次调用模型,并让模型将结果汇总(总结、解释)给用户 404 | 405 |
406 | 407 | 🪄 函数调用的重要意义: 408 | 409 | - 为用户函数定义了官方统一的描述格式(基于 [JSON Schema](https://json-schema.org/understanding-json-schema/),代价是计入输入 Token) 410 | - 为用户提供了一个“后门”确保对话可以输出 JSON 格式数据(有效简化了提示) 411 | 412 | --- 413 | level: 2 414 | --- 415 | 416 | # 🌰 函数调用的基本流程示例 417 | 418 | 在如下示例中,我们要求模型查询波士顿的温度,并提供了对应的可用函数供调用 419 | 420 | 421 | 422 | --- 423 | level: 2 424 | --- 425 | 426 | # 🌰 自主选择函数进行问答的示例(函数准备) 427 | 428 | 在如下示例中,我们准备两个函数定义,分别是:获取当日天气预报、获取多日的天气预报 429 | 430 | 431 | 432 | --- 433 | level: 2 434 | --- 435 | 436 | # 🌰 自主选择函数进行问答的示例(问答过程) 437 | 438 | 在问答阶段,针对不同的提示,模型可以自主选择合适的函数调用并提供参数 439 | 440 | 441 | 442 | --- 443 | layout: quote 444 | --- 445 | 446 | # OpenAI Functions 的衍生 447 | 448 | 巧用模型自主填充函数参数的特性可以做些什么? 449 | 450 | --- 451 | level: 2 452 | --- 453 | 454 | # 🌰 函数调用能力的衍生:文本提取 455 | 456 | 在如下示例中,利用函数提取文本中目标内容并进行 JSON 格式化输出 457 | 458 | 459 | 460 | --- 461 | level: 2 462 | --- 463 | 464 | # 🌰 函数调用能力的衍生:文本标签 465 | 466 | 在如下示例中,利用函数推测文本相关内容并进行 JSON 格式化输出 467 | 468 | 469 | 470 | --- 471 | layout: quote 472 | hideInToc: true 473 | --- 474 | 475 | # 还有哪些接口值得关注? 476 | 477 | 还有一些看似“平平无奇”的接口 😄 478 | 479 | --- 480 | 481 | # 模型调优 API:Fine-tunes 482 | 483 | 面向私域数据优化模型;可访问 [使用指南](https://platform.openai.com/docs/guides/fine-tuning) 及 [接口明细](https://platform.openai.com/docs/api-reference/fine-tunes) 了解所有接口及其参数应用 484 | 485 | 微调(Fine-tuning)的收益主要包括: 486 | 487 | - 相比提示工程的有限输入,可以训练更多数据(通常是文件级别) 488 | - 训练后针对私域数据,可以使用更短的提示词,得到更快更好的结果 489 | 490 |
491 | 492 | 哪些模型可以被微调: 493 | 494 | - 目前只支持 4 个基础模型:`davinci`、`curie`、`babbage`、`ada` 495 | - 注意这些不是其它接口所使用的指令优化模型,例如 `text-davinci-003` 496 | - 模型微调的费用详见 OpenAI [官方报价](https://openai.com/pricing#language-models)(分为两类:训练、使用) 497 | - 训练数据需要使用 [JSONL](https://jsonlines.org/) 格式,每行都是一对 `prompt`-`completion` 数据(参见 [训练数据准备工具](https://platform.openai.com/docs/guides/fine-tuning)) 498 | - 用户微调过的模型可以持续地 [再次进行微调](https://platform.openai.com/docs/guides/fine-tuning/continue-fine-tuning-from-a-fine-tuned-model) 499 | 500 | --- 501 | 502 | # 图片生成 API:Images 503 | 504 | 基于文化或图片来生成图片;可访问 [使用指南](https://platform.openai.com/docs/guides/images) 及 [接口明细](https://platform.openai.com/docs/api-reference/images) 了解所有接口及其参数应用 505 | 506 | 🎯 目前使用的模型是 [DALL·E](https://platform.openai.com/docs/models/dall-e),其能力主要包括: 507 | 508 | - 根据文本提示从零开始创建图像 509 | - 根据新文本提示创建修改现有图像 510 | - 根据现有图像(最大 4MB)生成它的变体 511 | 512 |
513 | 514 | > 💡 可访问 [DALL·E 预览应用](https://labs.openai.com/) 来体验图片生成效果(竟然还收费卖积点 😼) 515 | 516 |
517 | 518 | 🚧 目前接口在使用上的一些限制: 519 | 520 | - 图片数量:`1` 至 `10` 张 521 | - 图片尺寸:`256x256`,`512x512`,`1024x1024`(越小生成的越快) 522 | - 提示工程:修改图片需要重新描述完整的图片(即使已通过输入遮罩指定修改区域,[参考样例](https://github.com/openai/openai-cookbook/blob/main/examples/dalle/How_to_create_dynamic_masks_with_DALL-E_and_Segment_Anything.ipynb)) 523 | 524 | --- 525 | 526 | # 语音成文 API:Audio 527 | 528 | STT(Speech to Text)语音转文本;可访问 [使用指南](https://platform.openai.com/docs/guides/speech-to-text) 及 [接口明细](https://platform.openai.com/docs/api-reference/audio) 了解所有接口及其参数应用 529 | 530 | 🎯 目前使用的模型是 [Whisper](https://openai.com/research/whisper)(`whisper-1`),其能力主要包括: 531 | 532 | - 将音频转录为音频所使用的任何语言文本 533 | - 将音频翻译并转录为英语文本 534 | 535 |
536 | 537 | 🚧 目前接口在使用上的一些限制: 538 | 539 | - 文件大小:上次最大不超过 25 MB 540 | - 文件格式:`mp3`、`mp4`、`mpeg`、`mpga`、`m4a`、`wav`、`webm` 541 | - 提示工程:使用提示来提高生成的转录文本的质量,仅提供对生成的音频的有限控制([参考样例](https://github.com/openai/openai-cookbook/blob/main/examples/Whisper_prompting_guide.ipynb)) 542 | - 对于纠正模型在音频中经常错误识别的特定单词或首字母缩略词非常有帮助 543 | - 有些语言可以以不同的方式书写(例如简体中文和繁体中文),可以通过提示写作风格来选定 544 | - 为了保留被拆分为段的文件的上下文,可以使用前一段的记录提示模型 545 | 546 | --- 547 | src: ../../pages/common/refs.md 548 | --- 549 | 550 | --- 551 | src: ../../pages/common/end.md 552 | --- -------------------------------------------------------------------------------- /103-prompt-landscape/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /103-prompt-landscape/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /103-prompt-landscape/ --out ../../dist/103-prompt-landscape", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/103-prompt-landscape.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.43.7", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /103-prompt-landscape/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/103-prompt-landscape.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # Hub 提示词面面观 33 | 34 | LangChain Hub Prompt Landscape 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | src: ../../pages/common/toc.md 63 | --- 64 | 65 | --- 66 | layout: iframe-right 67 | url: https://blog.langchain.dev/the-prompt-landscape/ 68 | --- 69 | 70 | # Hub 热门提示词 🔥 71 | 72 | Popular Prompts in LangChain Hub 73 | 74 | 社区中各种不同用例的提示词在不断涌现 75 | A variety of prompts for different uses-cases have emerged. 76 | 77 | - [Prompt Engineering Guide](https://www.promptingguide.ai/) - [@dair_ai](https://twitter.com/dair_ai) 78 | - [Prompt Engineering](https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/) - [Lilian Weng](https://lilianweng.github.io/) 79 | 80 |
81 | 82 | LangChain Hub 推出一个多月以来也积累了丰富的提示词,大致可以被总结为十类用例 83 | Below we provide an overview of the major themes in prompting that we’ve seen since the launch of LangChain Hub and highlight interesting examples. 84 | 85 | --- 86 | layout: image 87 | image: https://blog.langchain.dev/content/images/size/w1000/2023/10/image-19.png 88 | --- 89 | 90 | --- 91 | layout: image 92 | image: https://blog.langchain.dev/content/images/size/w1000/2023/10/image-21.png 93 | --- 94 | 95 | --- 96 | 97 | # ✍️ 场景写作(Writing) 98 | 99 | Keywords: Writing Editor / Style, Content Generation 100 | 101 | 随着提示工程的普及,制作多样化内容的提示也不断增多(例如,邮件、博客文章、推文、教育学习材料) 102 | There's been a proliferation of prompts for producing diverse content (e.g. emails, blog posts, tweet threads, learning materials). 103 | 104 | - [SaaS User On-Boarding Email](https://smith.langchain.com/hub/gitmaxd/onboard-email): 生成引人注目的 SaaS 平台注册欢迎邮件 105 | - [Blog Generator](https://smith.langchain.com/hub/hardkothari/blog-generator):根据提供的上下文创建结构良好的博客文章 106 | - [Tweet from Text](https://smith.langchain.com/hub/hardkothari/tweet-from-text):在字数限制内、面向特定受众,制作简洁有效的推文 107 | - [Podcaster Tweet Thread](https://smith.langchain.com/hub/julia/podcaster-tweet-thread):给定播客的文字脚本,编写一条吸引眼球的推文 108 | - [Test Question Making](https://smith.langchain.com/hub/gregkamradt/test-question-making):为特定问题的测试(考试)创建一组精心设计的答案 109 | 110 |
另外,随着大语言模型的不断成熟,还有一些“绑定特定语言模型“的通用写作提示也在不断涌现 111 | Prompts to improve writing have widespread appeal given the impressive displays of creativity from specific LLMs. 112 | 113 | - Matt Shumer 编写的基于 GPT-4 模型的 [写作助手](https://smith.langchain.com/hub/rlm/matt-shumer-writing) 和 [风性化写作助手](https://smith.langchain.com/hub/rlm/matt-shumer-writing-style) 114 | 115 | @mattshumer_’s popular GPT-4 prompts provide ways to improve writing clarity or customize the style of LLM-generated text. 116 | 117 | --- 118 | layout: iframe 119 | url: https://smith.langchain.com/hub/gitmaxd/onboard-email 120 | --- 121 | 122 | --- 123 | layout: iframe 124 | url: https://smith.langchain.com/hub/rlm/matt-shumer-writing 125 | --- 126 | 127 | --- 128 | layout: iframe 129 | url: https://smith.langchain.com/hub/rlm/matt-shumer-writing-style 130 | --- 131 | 132 | --- 133 | 134 | # ⏳ 信息总结(Summarization) 135 | 136 | Keywords: Chain-of-density (CoD), Document Summerization 137 | 138 | [内容总结](https://blog.langchain.dev/llms-to-improve-documentation/) 是 LLM 的一个强大用例:例如 [Anthropic Claude 2](https://www.anthropic.com/index/claude-2),可以吸收超过 70 页的内容进行直接总结 139 | Summarization of content is a powerful LLM use-case. Longer context LLMs, e.g. Claude2, can absorb > 70 pages for direct summarization. 140 | 141 | [Chain of Density](https://browse.arxiv.org/pdf/2309.04269.pdf) 之类的提示技术提供了一种补充方法,从而产生密集且人性化的更好的摘要 142 | Prompting techniques like chain of density offer a complimentary approach, resulting in dense yet human-preferable summaries. 143 | 144 | - [Chain of Density](https://smith.langchain.com/hub/lawwu/chain_of_density):对给定文章(多次循环)生成越来越简洁、实体密集的摘要 145 | - [Anthropic Paper QA](https://smith.langchain.com/hub/hwchase17/anthropic-paper-qa):基于 Claude 2 的论文内容总结和审阅 146 | - [YouTube Transcript to Article](https://smith.langchain.com/hub/muhsinbashir/youtube-transcript-to-article):获取给定的 YouTube 视频文字并将其转换为结构良好且引人入胜的文章 147 | 148 |
此外,摘要可以应用于多种内容类型,例如聊天对话或特定于领域的数据([财务表摘要](https://smith.langchain.com/hub/hwchase17/financial-table-insights)) 149 | In addition, summarization can be applied to diverse content types like chat conversations or domain specific data 150 | 151 | --- 152 | layout: iframe 153 | url: https://smith.langchain.com/hub/lawwu/chain_of_density 154 | --- 155 | 156 | --- 157 | layout: iframe 158 | url: https://smith.langchain.com/hub/hwchase17/anthropic-paper-qa 159 | --- 160 | 161 | --- 162 | layout: iframe 163 | url: https://smith.langchain.com/hub/muhsinbashir/youtube-transcript-to-article 164 | --- 165 | 166 | --- 167 | layout: iframe 168 | url: https://smith.langchain.com/hub/hwchase17/financial-table-insights 169 | --- 170 | 171 | --- 172 | layout: two-cols 173 | --- 174 | 175 | # 📋 信息提取(Extraction) 176 | 177 | Keywords: Knowledge Graph Triples, Function Calling 178 | 179 | LLM 可以是提取特定格式文本的强大工具,目前比较有代表性的是 OpenAI 的 [Function Calling](https://openai.com/blog/function-calling-and-other-api-updates) 功能 180 | LLMs can be powerful tools for extracting text in particular formats, often aided by OpenAI's function calling. 181 | 182 | 有些类库提供基于 Function Calling 的信息抽取功能,例如 [Instructor](https://jxnl.github.io/instructor/) 183 | Some frameworks developed to support it, such as Instructor. 184 | 185 | Hub 中也有针对特定提取任务设计的提示词,例如进行知识图谱三元组提取 186 | We've also seen prompts designed for specific extraction tasks, such as knowledge graph triple extraction. 187 | 188 | - [Instagraph](https://instagraph.ai/), [Text-to-Graph Playground](https://twitter.com/RLanceMartin/status/1691880034058064365) 189 | 190 | ::right:: 191 | 192 | 193 | 194 | --- 195 | layout: iframe 196 | url: https://smith.langchain.com/hub/langchain/knowledge-triple-extractor 197 | --- 198 | 199 | --- 200 | 201 | # 👩‍💻 代码分析和生成(Code Analysis and Generation) 202 | 203 | Keywords: Code Review / Analysis,Code Generation 204 | 205 | 代码分析是最流行的 LLM 用例之一,Hub 中也有不少提示词是在这方面起作用的: 206 | Code analysis is one of the most popular LLM use-cases, we've seen a number of prompts related to this theme: 207 | 208 | - [Open Interpreter System](https://smith.langchain.com/hub/chuxij/open-interpreter-system):驱动 [Open Interpreter](https://www.pluralsight.com/resources/blog/data/chatgpt-code-interpreter-plugin-guide) 通过执行代码完成用户提出的各种目标 209 | - [Virtual Github PR Reviews](https://smith.langchain.com/hub/homanp/github-code-reviews):对 GitHub 代码仓库中的 Pull Request 进行代码审查 210 | 211 | --- 212 | layout: iframe 213 | url: https://smith.langchain.com/hub/chuxij/open-interpreter-system 214 | --- 215 | 216 | --- 217 | layout: iframe 218 | url: https://smith.langchain.com/hub/homanp/github-code-reviews 219 | --- 220 | 221 | --- 222 | 223 | # 🤖️ 提示优化(Prompt Optimization) 224 | 225 | Keywords: Image Creation, Instruction Improvement 226 | 227 | [Deepmind 的论文](https://arxiv.org/pdf/2309.03409.pdf) 指出:LLM 可以优化提示。 228 | The Deepmind work showing that LLMs can optimize prompts. 229 | 230 | 我们沿着这些思路看到了许多有趣的提示词;一个很好的例子是 [Midjourney](https://www.midjourney.com/) 的提示优化,如下所示: 231 | We’ve seen a number of interesting prompts along these lines; one good example is for Midjourney, as shown below: 232 | 233 |
234 | 235 | 236 |

Freddie Mercury electrifying the San Francisco Pride Parade stage, shining in a gleaming golden outfit, iconic microphone stand in hand, evoking the hyper-realistic style of Caravaggio, vivid and dynamic --ar 16:9 --q 2)

237 | Freddie Mercury performing at the 2023 San Francisco Pride Parade hyper realistic 238 |
239 |
240 | 241 | --- 242 | layout: iframe 243 | url: https://smith.langchain.com/hub/aemonk/midjourney_prompt_generator 244 | --- 245 | 246 | --- 247 | layout: iframe 248 | url: https://smith.langchain.com/hub/hardkothari/prompt-maker 249 | --- 250 | 251 | --- 252 | layout: iframe-right 253 | url: https://smith.langchain.com/hub/rlm/rag-prompt 254 | title: 📓 检索增强生成(RAG) 255 | --- 256 | 257 | # 📓 检索生成(RAG) 258 | 259 | Keywords: Adding Context 260 | 261 | 检索增强生成是现在非常流行的 LLM 应用场景 262 | RAG is a popular LLM application. 263 | 264 | ![](https://blog.langchain.dev/content/images/2023/10/image-15.png) 265 | 266 |
它将 LLM 的推理能力与外部数据源的内容结合起来,这对于 [企业数据](https://www.glean.com/blog/how-to-build-an-ai-assistant-for-the-enterprise) 来说尤其强大 267 | RAG has particular promise because it marries the reasoning capability of LLMs with the content of external data sources, which is particularly powerful for enterprise data. 268 | 269 | --- 270 | layout: iframe 271 | url: https://smith.langchain.com/hub/rlm/rag-prompt-llama 272 | --- 273 | 274 | --- 275 | layout: iframe 276 | url: https://smith.langchain.com/hub/rlm/rag-prompt-mistral 277 | --- 278 | 279 | --- 280 | layout: iframe-right 281 | url: https://smith.langchain.com/hub/rlm/text-to-sql 282 | --- 283 | 284 | # 🗄️ SQL 285 | 286 | Keywords: Text-to-SQL Query 287 | 288 | 由于企业数据通常从 SQL 数据库中获取,因此使用 LLM 作为 SQL 查询的自然语言交互入口是一个合理的应用场景 289 | Because enterprise data is often captures in SQL databases, there is great interest in using LLMs as a natural language interface for SQL. 290 | 291 | 目前已经有[一些论文](https://arxiv.org/pdf/2204.00498.pdf)指出:给定数据表的一些特定信息,LLM 可以生成 SQL,包括每个 `CREATE TABLE` 描述、`SELECT` 语句的三个示例行 292 | A number of papers have reported that LLMs can generate SQL given some specific information about the table, including a CREATE TABLE description for each table followed by three example rows in a SELECT statement. 293 | 294 | 295 | LangChain 也提供了 [查询 SQL 数据库](https://python.langchain.com/docs/use_cases/qa_structured/sql) 的工具 296 | LangChain has numerous tools for querying SQL databases. 297 | 298 | 299 | --- 300 | 301 | # 📝 评价打分(LLM Graders) 302 | 303 | Keywords: LLM Evaluators, Bias Checking 304 | 305 | 把 LLM 用作评分器是一个很有趣的想法,核心思想是利用 LLM 评判一个响应结果和基准答案的匹配度 306 | The central idea of using LLMs as graders is to utilize the discrimination of an LLM to grade a response relative to a ground truth answer. 307 | 308 | - [Model Evaluator](https://smith.langchain.com/hub/simonp/model-evaluator):根据自定义标准对模型或现有的 LangSmith 运行/数据集进行评分 309 | - [Assumption Checker](https://smith.langchain.com/hub/smithing-gold/assumption-checker):识别查询中的关键假设,然后形成可检查的事实并评估这些假设的问题 310 | 311 |
事实上,包括 [OpenAI Cookbook](https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/How_to_eval_abstractive_summarization.ipynb),以及 [LangChain](tps://twitter.com/hwchase17/status/1692220493657485674)、[LlamaIndex](https://twitter.com/jerryjliu0/status/1703074710077260092) 都展示过这种使用 LLM 来打分的技巧 312 | In fact, this idea that has been broadly showcased in OpenAI cookbooks and open source projects. 313 | 314 |
LangSmith 的评价系统也做了很多类似的 [测试和评估](https://docs.smith.langchain.com/evaluation) 功能探索 315 | Much of the work on LangSmith has focused on evaluation support. 316 | 317 | --- 318 | layout: iframe 319 | url: https://smith.langchain.com/hub/simonp/model-evaluator 320 | --- 321 | 322 | --- 323 | layout: iframe 324 | url: https://smith.langchain.com/hub/smithing-gold/assumption-checker 325 | --- 326 | 327 | --- 328 | layout: two-cols 329 | title: 📚 合成数据生成(Synthetic Data Generation) 330 | --- 331 | 332 | # 📚 合成数据生成(Synthetic Data Gen) 333 | 334 | Keywords: Fine-tuning Data, Evaluation Tests 335 | 336 | 微调 LLM 是引导 LLM 行为的主要方法之一,但是收集用于微调的训练数据是一个挑战 337 | Fine-tuning LLMs is one of the primary ways to steer LLM behavior, while gathering training data for fine-tuning is a challenge. 338 | 339 |
一个思路:使用 LLM 生成微调训练所需要的合成数据集 340 | Many work has focused on using LLMs to generate synthetic datasets. 341 | 342 | - [Synthetic Training Data](https://smith.langchain.com/hub/gitmaxd/synthetic-training-data):OpenAI 训练数据生成 343 | - [Question Answer Pair](https://smith.langchain.com/hub/homanp/question-answer-pair):基于上下文的问答集合生成 344 | 345 | ::right:: 346 | 347 | 348 | 349 | --- 350 | layout: iframe 351 | url: https://smith.langchain.com/hub/gitmaxd/synthetic-training-data 352 | --- 353 | 354 | --- 355 | layout: iframe 356 | url: https://smith.langchain.com/hub/homanp/question-answer-pair 357 | --- 358 | 359 | --- 360 | layout: image-right 361 | image: https://pbs.twimg.com/media/F5_OeQdXoAAkAxo?format=jpg&name=medium 362 | --- 363 | 364 | # 🧠 推论(Reasoning) 365 | 366 | Keywords: Chain-of-Thought, Agents (ReAct) 367 | 368 | [论文](https://arxiv.org/pdf/2309.03409.pdf)研究表明:[思考链](https://arxiv.org/abs/2201.11903)有助于提升 LLM 的准确率 369 | This has found broad appeal because it improves many reasoning tasks by a large margin and is easy to implement. 370 | 371 | - `Let's think step by step` 372 | - `Take a deep breath and work on this problem step-by-step` 373 | - [Tree of Thought](https://arxiv.org/abs/2305.10601):思考链 ➡️ 思考树 374 | 375 | [思考链](https://twitter.com/cwolferesearch/status/1657122778984660993)提示还可以附加到许多任务中,并且对于 [Agent](https://lilianweng.github.io/posts/2023-06-23-agent/) 来说变得尤为重要。例如,[ReAct Agent](https://www.promptingguide.ai/techniques/react) 以交错的方式将工具使用与推理结合起来 376 | Reasoning prompts as shown above can be appended as simple instructions to many tasks and have become particularly important for agents. 377 | 378 | --- 379 | layout: image 380 | image: https://pbs.twimg.com/media/Fv9G3cFWwAA6yTV?format=jpg&name=4096x4096 381 | --- 382 | 383 | --- 384 | layout: iframe 385 | url: https://smith.langchain.com/hub/shoggoth13/react-chat-agent 386 | --- 387 | 388 | --- 389 | layout: iframe 390 | url: https://smith.langchain.com/hub/jacob/langchain-tsdoc-research-agent 391 | --- 392 | 393 | --- 394 | src: ../../pages/common/refs.md 395 | --- 396 | 397 | --- 398 | src: ../../pages/common/end.md 399 | --- 400 | -------------------------------------------------------------------------------- /201-langchain-modules/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /201-langchain-modules/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /201-langchain-modules/ --out ../../dist/201-langchain-modules", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/201-langchain-modules.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.42.4", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /201-langchain-modules/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/201-langchain-modules.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # LangChain 模块解析(上) 33 | 34 | LangChain Modules Hands-on 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | src: ../../pages/common/toc.md 63 | --- 64 | 65 | --- 66 | layout: iframe 67 | url: https://embeds.onemodel.app/d/iframe/IDSmkjp32ePfdFqKcuCSFsyUZyTi0DkPJ3xWpKhcoIsAfQzzYdTlo4KYZimY 68 | hideInToc: true 69 | --- 70 | 71 | --- 72 | layout: iframe 73 | url: //player.bilibili.com/player.html?aid=786400485&bvid=BV1214y1X7Aq&cid=1211541734 74 | hideInToc: true 75 | --- 76 | 77 | --- 78 | 79 | # LangChain 核心模块概览 80 | 81 | 基于 [LangChain Modules Overview](https://embeds.onemodel.app/d/iframe/IDSmkjp32ePfdFqKcuCSFsyUZyTi0DkPJ3xWpKhcoIsAfQzzYdTlo4KYZimY) 模块架构图一起来认识一下六大模块,参见 [官方文档](https://docs.langchain.com/docs/category/components) 82 | 83 | ###### 201 教程的关注模块 84 | 85 | - Model I/O:管理大语言模型([Models](https://docs.langchain.com/docs/components/models/)),及其输入([Prompts](https://docs.langchain.com/docs/components/prompts/))和格式化输出([Output Parsers](https://docs.langchain.com/docs/components/prompts/output-parser)) 86 | - 数据流:(Parser 生成的输出格式提示 ➡️)Prompt ➡️ Model ➡️ Output Parser 87 | - Data Connection:管理主要用于建设私域知识(库)的向量数据存储([Vector Stores](https://docs.langchain.com/docs/components/indexing/vectorstore))、内容数据获取([Document Loaders](https://docs.langchain.com/docs/components/indexing/document-loaders))和转化([Transformers](https://docs.langchain.com/docs/components/indexing/text-splitters)),以及向量数据查询([Retrievers](https://docs.langchain.com/docs/components/indexing/retriever)) 88 | - 数据流:Loaders ➡️(Transformers ➡️)Embeddings Model ➡️ Vector Stores ➡️ Retrievers 89 | - Memory:用于存储和获取 [对话历史记录](https://docs.langchain.com/docs/components/memory/) 的功能模块 90 | 91 |
92 | 93 | ###### 202 教程的关注模块 94 | 95 | - Chains:用于串联 Memory ↔️ Model I/O ↔️ Data Connection,以实现 [串行化](https://docs.langchain.com/docs/components/chains/) 的连续对话、推测流程 96 | - Agents:基于 Chains [进一步串联](https://docs.langchain.com/docs/components/agents/) 工具([Tools](https://docs.langchain.com/docs/components/agents/tool)),从而将大语言模型的能力和本地、云服务能力结合 97 | - Callbacks:提供了一个回调系统,可连接到 LLM 申请的各个阶段,便于进行日志记录、追踪等数据导流 98 | 99 | --- 100 | src: ../../pages/playground/langchain.md 101 | --- 102 | 103 | --- 104 | layout: quote 105 | --- 106 | 107 | # Model I/O · 选择你的模型 108 | 109 | 同时也准备好你的输入、设定好输出的格式(结构) 110 | 111 | --- 112 | level: 2 113 | --- 114 | 115 | # Model I/O 三元组 116 | 117 | - Prompts:模板化、动态选择和管理模型输入 118 | - Language Models:通过通用接口调用语言模型 119 | - Output Parsers:从模型输出中提取信息 120 | 121 | ![](https://js.langchain.com/assets/images/model_io-1f23a36233d7731e93576d6885da2750.jpg) 122 | 123 | --- 124 | level: 2 125 | --- 126 | 127 | # Models:一切的缘起 128 | 129 | 在 LangChain 中,把模型分成三类:LLM 大语言模型,Chat 对话模型,Embeddings 嵌入模型 130 | 131 | - [LLM](https://js.langchain.com/docs/modules/model_io/models/llms/):将文本字符串作为输入,并返回续写文本的应用模型 132 | 133 | 134 | 135 | --- 136 | level: 2 137 | --- 138 | 139 | # Models:一切的缘起 (cont.) 140 | 141 | 在 LangChain 中,把模型分成三类:LLM 大语言模型,Chat 对话模型,Embeddings 嵌入模型 142 | 143 | - [Chat](https://js.langchain.com/docs/modules/model_io/models/chat/):基于 LLM 支持并将聊天消息序列作为输入,并返回聊天消息的应用模型 144 | 145 | 146 | 147 | --- 148 | level: 2 149 | --- 150 | 151 | # Models 提高多个通用接口 152 | 153 | 通用接口也支持批处理调用,并返回更丰富的响应内容 154 | 155 | 156 | 157 | --- 158 | level: 2 159 | --- 160 | 161 | # Prompts 的模板能力 162 | 163 | [Prompt Template](https://js.langchain.com/docs/modules/model_io/prompts/prompt_templates/) 是一个带标记的文本字符串,可以接收来自最终用户的一组参数并生成提示 164 | 165 | 166 | 167 | --- 168 | level: 2 169 | --- 170 | 171 | # Prompts 的模板能力:Partial 172 | 173 | 模板也提供 [Partial](https://js.langchain.com/docs/modules/model_io/prompts/prompt_templates/partial) 的形式,用于分阶段的注入参数(变量内容) 174 | 175 | 176 | 177 | --- 178 | level: 2 179 | --- 180 | 181 | # Prompts 模板的组合 182 | 183 | 可以通过 [Pipeline](https://js.langchain.com/docs/modules/model_io/prompts/prompt_templates/prompt_composition) 来实现组合,它是一组提示模板,其中的每个模板将格式化,并按最终模板格式进行组合 184 | 185 | 186 | 187 | --- 188 | level: 2 189 | --- 190 | 191 | # Prompts 的示例选择器 192 | 193 | 当您有大量示例时,可能需要选择哪些要包含在提示中,示例选择器是负责执行此操作的工具 194 | 195 | 如下示例选择器 [根据长度选择](https://js.langchain.com/docs/modules/model_io/prompts/example_selectors/length_based) 要使用的示例,当我们担心构建的提示会超过上下文窗口的长度时,这非常有用 196 | 197 | 198 | 199 | --- 200 | level: 2 201 | --- 202 | 203 | # Output Parsers 结构化输出:列表 204 | 205 | 如下示例中,我们将模型的输出解析为 [具有特定长度和分隔符的列表](https://js.langchain.com/docs/modules/model_io/output_parsers/custom_list_parser) 206 | 207 | 208 | 209 | --- 210 | level: 2 211 | --- 212 | 213 | # Output Parsers 结构化输出:JSON(粗粒度) 214 | 215 | 如下示例中,我们将模型的输出解析为一个 [包含多个字段的 JSON 对象](https://js.langchain.com/docs/modules/model_io/output_parsers/structured) 216 | 217 | 218 | 219 | --- 220 | level: 2 221 | --- 222 | 223 | # Output Parsers 结构化输出:JSON(细粒度) 224 | 225 | 如下示例中,我们将模型的输出解析为一个结构被严格要求的 JSON 对象(Zod 格式) 226 | 227 | 228 | 229 | --- 230 | level: 2 231 | --- 232 | 233 | # Runnable Chain 0.0.121: LLM Chain 234 | 235 | 现在可以用管道直接把 Prompt ➡️ Model ➡️ Output Parser 串联起来 236 | 237 | 238 | 239 | --- 240 | layout: quote 241 | --- 242 | 243 | # Data Connection · 准备你的数据 244 | 245 | 获取数据,整理数据,存储数据,查询数据 246 | 247 | --- 248 | level: 2 249 | --- 250 | 251 | # Data Connection 的核心组件 252 | 253 | - Document Loaders & Transformers:从许多不同的源加载文档;然后拆分文档、删除冗余文档等 254 | - Embedding Models:获取非结构化文本并将其转换为向量数据 255 | - Vector Stores:存储和搜索向量数据 256 | - Retrievers:从 Vector Stores 和其它数据源查询您的数据 257 | 258 | ![](https://js.langchain.com/assets/images/data_connection-c42d68c3d092b85f50d08d4cc171fc25.jpg) 259 | 260 | --- 261 | level: 2 262 | --- 263 | 264 | # Document Loaders 的丰富数据源 265 | 266 | Document Loaders 从文档源加载数据,并将数据转化成“文档”格式(一段文本和关联的元数据) 267 | 268 | 数据源可以是 [本地文件](https://js.langchain.com/docs/modules/data_connection/document_loaders/integrations/file_loaders/),也可以是 [在线文件](https://js.langchain.com/docs/modules/data_connection/document_loaders/integrations/web_loaders/);在如下示例中,我们分别从 GitHub 和网页加载我们教程的内容 269 | 270 | 271 | 272 | --- 273 | level: 2 274 | --- 275 | 276 | # Document Transforms 的文本切分 277 | 278 | 文本切分的主要方式大体包括 “[按字符](https://js.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/recursive_text_splitter)”、“[按 Token](https://js.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/token)”、“[按代码](https://js.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/code_splitter)”;在如下示例中,我们主要演示前两种切分方式 279 | 280 | 281 | 282 | --- 283 | layout: iframe 284 | url: //player.bilibili.com/player.html?aid=489796063&bvid=BV1mN411z7EZ&cid=1234039938 285 | hideInToc: true 286 | --- 287 | 288 | --- 289 | level: 2 290 | --- 291 | 292 | # Vector Stores 向量存储 293 | 294 | 存储和搜索非结构化数据的最常见方法之一是嵌入它并存储生成的嵌入向量 295 | 296 | [向量存储](https://js.langchain.com/docs/modules/data_connection/vectorstores/) 负责存储嵌入式数据并为您执行向搜索 —— 查询“最相似”的嵌入向量;向量由 [Embeddings](https://js.langchain.com/docs/modules/data_connection/text_embedding/) 模型生成 297 | 298 | ![](https://python.langchain.com/assets/images/vector_stores-9dc1ecb68c4cb446df110764c9cc07e0.jpg) 299 | 300 | --- 301 | level: 2 302 | --- 303 | 304 | # 向量存储的相似度搜索 305 | 306 | 在如下示例中,我们展示 [Pinecone 云服务](https://js.langchain.com/docs/modules/data_connection/vectorstores/integrations/pinecone) 向量存储的搜索(数据写入部分参考 [工具函数](https://www.val.town/v/webup.getVectorStoreBuilder)) 307 | 308 | 309 | 310 | --- 311 | level: 2 312 | --- 313 | 314 | # Retrievers 从各个文档源检索 315 | 316 | [Retrievers](https://js.langchain.com/docs/modules/data_connection/retrievers/) 比向量存储更通用,它不需要能够存储文档,只需返回(或检索)文档 317 | 318 | - 向量存储是最常用的文档源,但也可以从其它本地、云上的文档源进行数据的检索 319 | - [Self-Query Retriever](https://js.langchain.com/docs/modules/data_connection/retrievers/how_to/self_query/):顾名思义,这是一种具有查询自身能力的检索器 320 | - 即给定任何自然语言查询,Retriever 通过构造 LLM Chain 编写结构化查询,并将其应用于底层向量存储 321 | 322 | ![](https://s2.loli.net/2023/07/30/WQSGv8iDU9w4Fy6.jpg) 323 | 324 | --- 325 | level: 2 326 | --- 327 | 328 | # 🌰 Self-Query Retriever 329 | 330 | 331 | 332 | --- 333 | level: 2 334 | --- 335 | 336 | # Retrievers 从各个文档源检索(续) 337 | 338 | 检索的一项挑战是,通常不知道将数据引入系统时,文档存储系统将面临哪些特定查询 339 | 340 | - 与查询最相关的信息可能被隐藏在包含大量不相关文本中,传递完整文档成本更高且响应较差 341 | - [Contextual Compression Retriever](https://js.langchain.com/docs/modules/data_connection/retrievers/how_to/contextual_compression/):上下文压缩旨在解决此问题 342 | - 使用给定查询的上下文来压缩它们,以便只返回相关信息,而不是立即按原样返回检索到的文档 343 | 344 | ![](https://s2.loli.net/2023/07/30/HQx5JIGrEVPfz8R.jpg) 345 | 346 | --- 347 | level: 2 348 | --- 349 | 350 | # Runnable Chain 0.0.121: LLM Chain + Retriever 351 | 352 | 可以用管道直接把 Prompt ➡️ Model ➡️ Output Parser ➡️ Retriever 串联起来 353 | 354 | 355 | 356 | --- 357 | level: 2 358 | --- 359 | 360 | # Runnable Chain 0.0.121: LLM Chain + Retriever 361 | 362 | 在上个示例中,我们将字符串输入直接传递到链路中;如希望链路接受多个输入,可以传递函数映射来解析输入 363 | 364 | 365 | 366 | --- 367 | level: 2 368 | --- 369 | 370 | # Runnable Chain 0.0.121: LLM Chain + Retriever 371 | 372 | 在上个示例中,我们使链路接受了多个输入;我们还可以通过格式化函数添加对话历史记录 373 | 374 | 375 | 376 | --- 377 | layout: quote 378 | --- 379 | 380 | # Memory · 记录你的对话 381 | 382 | 对话记录是保持链路状态的基石 383 | 384 | --- 385 | level: 2 386 | --- 387 | 388 | # Memory 对话状态存储 389 | 390 | Memory 负责在用户与大语言模型的交互过程中保留状态 391 | 392 | ![](https://python.langchain.com/assets/images/memory_diagram-0627c68230aa438f9b5419064d63cbbc.png) 393 | 394 | --- 395 | level: 2 396 | --- 397 | 398 | # Memory 对话状态存储 399 | 400 | - [Memory](https://js.langchain.com/docs/modules/memory/) 的作用可以归结为从一系列聊天消息中摄取、捕获、转换和提取知识 401 | - Memory 可以返回多条信息(例如最近的 N 条消息和摘要)或者所有以前的消息 402 | 403 |
404 | 405 | 406 | --- 407 | level: 2 408 | --- 409 | 410 | # Memory 的多样化存取方式 411 | 412 | Memory 不仅可以整存整取,还可以利用大语言模型加工并返回处理后的内容 413 | 414 | - 通过 LLM 模型对记录内容进行总结 415 | 416 | 417 | 418 | --- 419 | level: 2 420 | --- 421 | 422 | # Memory 的多样化存取方式:Vector Store 423 | 424 | 通过 Vector Store 也可以对记录内容进行相似度匹配后返回 425 | 426 | 427 | 428 | --- 429 | src: ../../pages/common/refs.md 430 | --- 431 | 432 | --- 433 | src: ../../pages/common/end.md 434 | --- 435 | -------------------------------------------------------------------------------- /202-langchain-chains/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /202-langchain-chains/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /202-langchain-chains/ --out ../../dist/202-langchain-chains", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/202-langchain-chains.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.43.5", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /202-langchain-chains/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/202-langchain-chains.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # LangChain 模块解析(中) 33 | 34 | LangChain Chains Hands-on 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | hideInToc: true 63 | --- 64 | 65 | # 教程大纲 66 | 67 | 68 | 69 | --- 70 | layout: iframe 71 | url: https://embeds.onemodel.app/d/iframe/cl8GryOek12pB78SZZYZCsJSJsS159pNgqjS19zQWC3tka5TXz9rqLmqXORI 72 | hideInToc: true 73 | --- 74 | 75 | --- 76 | layout: iframe 77 | url: //player.bilibili.com/player.html?aid=275180495&bvid=BV1SF411C7Zn&cid=1244328447 78 | hideInToc: true 79 | --- 80 | 81 | --- 82 | layout: quote 83 | --- 84 | 85 | # Runnable Sequence 86 | 87 | LangChain Expression Language (LCEL) 的核心 88 | 89 | --- 90 | level: 2 91 | --- 92 | 93 | # Runnable 对象简介 94 | 95 | 把一个个 Runnable 对象串联起来,就构成了 Runnable Sequence 96 | 97 |

Runnable 对象的定义:支持以下三个实例方法的对象

98 | 99 | - `invoke`:对输入直接进行链式调用 100 | - `batch`:对输入列表进行批量的链式调用 101 | - `stream`:(流式)分块返回响应(需要 Model、Parser 等支持) 102 | 103 |
104 | 105 |

Runnable 对象的输入输出:各有不同,并非统一(以下以 JS/TS SDK 为例)

106 | 107 | - Prompt:`Object` ➡️ `PromptValue` 108 | - LLM Model:`String` ➡️ `String` 109 | - Chat Model:一组 `ChatMessage` ➡️ `ChatMessage` 110 | - Parser:Model 的输出 ➡️ 不同 Parser 对应的数据结构 111 | - Retriever:`String` ➡️ 一组 `Document` 112 | 113 | --- 114 | level: 2 115 | --- 116 | 117 | # Runnable 对象的串联 118 | 119 | - JS/TS 中可用的实例方法:`runnable.pipe(runnable)` 120 | - JS/TS 中可用的静态方法:`RunnableSequence.from([...runnables ])` 121 | 122 | ```ts {6-9|11-13|15-17|all} 123 | import { PromptTemplate } from "langchain/prompts"; 124 | import { OpenAI } from "langchain/llm/openai"; 125 | import { RunnableSequence } from "langchain/schema/runnable"; 126 | import { StringOutputParser } from "langchain/schema/output_parser"; 127 | 128 | /* 准备 Runnable 对象 */ 129 | const model = new OpenAI({}); 130 | const promptTemplate = PromptTemplate.fromTemplate("Tell me a joke about {topic}"); 131 | const outputParser = new StringOutputParser(); 132 | 133 | /* 串联 Runnable 对象 */ 134 | // const chain = promptTemplate.pipe(model).pipe(outputParser); 135 | const chain = RunnableSequence.from([promptTemplate, model, outputParser]); 136 | 137 | /* 调用 Runnable Sequence */ 138 | const result = await chain.invoke({ topic: "bears" }); 139 | // const result = await chain.batch([{ topic: "bears" }, { topic: "dears" }]); 140 | ``` 141 | 142 | --- 143 | layout: iframe 144 | url: https://smith.langchain.com/public/d6e1b8d9-bd25-431b-9e5a-6b852cf1e0e0/r 145 | --- 146 | 147 | --- 148 | level: 2 149 | --- 150 | 151 | # Runnable 对象绑定参数 152 | 153 | - JS/TS 中可用的实例方法:`runnable.bind( ...kwargs )` 154 | 155 | ```ts {8-28|30-36|all} {maxHeight:'80%'} 156 | import { PromptTemplate } from "langchain/prompts"; 157 | import { ChatOpenAI } from "langchain/chat_models/openai"; 158 | 159 | /* 准备 Runnable 对象 */ 160 | const prompt = PromptTemplate.fromTemplate(`Tell me a joke about {subject}`); 161 | const model = new ChatOpenAI({}); 162 | 163 | /* 准备 Runnable 对象的附加参数 */ 164 | const functionSchema = [ 165 | { 166 | name: "joke", 167 | description: "A joke", 168 | parameters: { 169 | type: "object", 170 | properties: { 171 | setup: { 172 | type: "string", 173 | description: "The setup for the joke", 174 | }, 175 | punchline: { 176 | type: "string", 177 | description: "The punchline for the joke", 178 | }, 179 | }, 180 | required: ["setup", "punchline"], 181 | }, 182 | }, 183 | ]; 184 | 185 | /* 串联 Runnable 对象,同时附加参数 */ 186 | const chain = prompt.pipe( 187 | model.bind({ 188 | functions: functionSchema, 189 | function_call: { name: "joke" }, 190 | }) 191 | ); 192 | 193 | /* 调用 Runnable Sequence */ 194 | const result = await chain.invoke({ subject: "bears" }); 195 | ``` 196 | 197 | --- 198 | layout: iframe 199 | url: https://smith.langchain.com/public/4f429737-3bf8-4ca6-b29f-f5dcb25ee07a/r 200 | --- 201 | 202 | --- 203 | level: 2 204 | --- 205 | 206 | # Runnable Map 207 | 208 | 当 Runnable 对象接收的输入需要被预处理时,可以使用一个 Map 结构提供支持 209 | 210 | - Map 中的每个属性都接收相同的参数,使用这些参数来调用各个属性对应的 Runnable 对象或函数 211 | - 调用的返回值用于填充 Map 对象,然后将该对象传递到序列中的下一个 Runnable 对象 212 | 213 | ```ts {9-11,14-18|14-22|all} {maxHeight:'75%'} 214 | import { PromptTemplate } from "langchain/prompts"; 215 | import { RunnableSequence } from "langchain/schema/runnable"; 216 | import { StringOutputParser } from "langchain/schema/output_parser"; 217 | import { OpenAI } from "langchain/chat_models/openai"; 218 | 219 | const prompt1 = PromptTemplate.fromTemplate(`What is the city {person} is from? Only respond with city name.`); 220 | const prompt2 = PromptTemplate.fromTemplate(`What country is the city {city} in? Respond in {language}.`); 221 | 222 | /* 构建第一个 Chain */ 223 | const model = new OpenAI({}); 224 | const chain = prompt1.pipe(model).pipe(new StringOutputParser()); 225 | 226 | const combinedChain = RunnableSequence.from([ 227 | /* 将第一个 Chain 的返回值和原始输入中的部分数据进行组合 */ 228 | { 229 | city: chain, 230 | language: (input) => input.language, 231 | }, 232 | /* 组合后的对象成为第二个 Chain 的输入 */ 233 | prompt2, 234 | model, 235 | new StringOutputParser(), 236 | ]); 237 | 238 | const result = await combinedChain.invoke({ person: "Chairman Mao", language: "Chinese" }); 239 | ``` 240 | 241 | --- 242 | layout: iframe 243 | url: https://smith.langchain.com/public/a013b8e0-bf9a-44d2-be05-d67975b8812b/r 244 | --- 245 | 246 | --- 247 | level: 2 248 | --- 249 | 250 | # Runnable Passthrough 251 | 252 | 当我们要从一个长长的 Runnable Sequence 中提取最头部的输入时,可以使用 Passthrough 透传机制 253 | 254 | ```ts {11-17|24,27-33|all} {maxHeight:'80%'} 255 | import { ChatOpenAI } from "langchain/chat_models/openai"; 256 | import { HNSWLib } from "langchain/vectorstores/hnswlib"; 257 | import { OpenAIEmbeddings } from "langchain/embeddings/openai"; 258 | import { PromptTemplate } from "langchain/prompts"; 259 | import { RunnableSequence, RunnablePassthrough } from "langchain/schema/runnable"; 260 | import { StringOutputParser } from "langchain/schema/output_parser"; 261 | import { Document } from "langchain/document"; 262 | 263 | const model = new ChatOpenAI({}); 264 | 265 | /* 为 RAG 场景准备 Retriever */ 266 | const vectorStore = await HNSWLib.fromTexts( 267 | ["mitochondria is the powerhouse of the cell"], 268 | [{ id: 1 }], 269 | new OpenAIEmbeddings() 270 | ); 271 | const retriever = vectorStore.asRetriever(); 272 | 273 | const prompt = PromptTemplate.fromTemplate(`Answer the question based only on the following context: 274 | {context} 275 | 276 | Question: {question}`); 277 | 278 | const serializeDocs = (docs: Document[]) => docs.map((doc) => doc.pageContent).join("\n"); 279 | 280 | const chain = RunnableSequence.from([ 281 | /* 根据 RAG 提示词模版的需求准备上下文和问题 */ 282 | { 283 | /* 将 Retriever 返回的一组文档拼接为上下文段落 */ 284 | context: retriever.pipe(serializeDocs), 285 | /* 通过 Passthrough 透传获取原始输入 */ 286 | question: new RunnablePassthrough(), 287 | }, 288 | prompt, 289 | model, 290 | new StringOutputParser(), 291 | ]); 292 | 293 | const result = await chain.invoke("What is the powerhouse of the cell?"); 294 | ``` 295 | 296 | --- 297 | layout: iframe 298 | url: https://smith.langchain.com/public/3fbc6896-9fbf-4555-aa39-a08095ce1834/r 299 | --- 300 | 301 | --- 302 | level: 2 303 | --- 304 | 305 | # Tool 也是一种 Runnable 对象 306 | 307 | 因此 Tool 是可以在 Runnable Sequence 中被串联的 308 | 309 | ```ts {12-16|all} 310 | import { SerpAPI } from "langchain/tools"; 311 | import { OpenAI } from "langchain/llm/anthropic"; 312 | import { PromptTemplate } from "langchain/prompts"; 313 | import { StringOutputParser } from "langchain/schema/output_parser"; 314 | 315 | const prompt = PromptTemplate.fromTemplate(`Turn the following user input into a search query for a search engine: 316 | 317 | {input}`); 318 | 319 | const model = new OpenAI({}); 320 | 321 | /* 准备 Web Search 工具 */ 322 | const search = new SerpAPI(); 323 | 324 | /* 直接将 Web Search 工具传入并调用 */ 325 | const chain = prompt.pipe(model).pipe(new StringOutputParser()).pipe(search); 326 | 327 | const result = await chain.invoke({ input: "Who is the current prime minister of Malaysia?" }); 328 | ``` 329 | 330 | --- 331 | layout: iframe 332 | url: https://smith.langchain.com/public/6a5c08ee-96d8-4c97-8cfc-038990c7260f/r 333 | --- 334 | 335 | --- 336 | level: 2 337 | --- 338 | 339 | # 在 Runnable Sequence 中引入 Memory 340 | 341 | Memory 可以被添加到任何 Runnable Sequence 中,本质和就是生成上下文文本填充到提示词中 342 | 343 | ```ts {13-19|22-31|39-40|all} {maxHeight:'80%'} 344 | import { ChatPromptTemplate, MessagesPlaceholder } from "langchain/prompts"; 345 | import { RunnableSequence } from "langchain/schema/runnable"; 346 | import { ChatAnthropic } from "langchain/chat_models/anthropic"; 347 | import { BufferMemory } from "langchain/memory"; 348 | 349 | const model = new ChatAnthropic(); 350 | const prompt = ChatPromptTemplate.fromMessages([ 351 | ["system", "You are a helpful chatbot"], 352 | new MessagesPlaceholder("history"), 353 | ["human", "{input}"], 354 | ]); 355 | 356 | /* 初始化 Memory 对象 */ 357 | const memory = new BufferMemory({ 358 | returnMessages: true, 359 | inputKey: "input", // by default 360 | outputKey: "output", // by default 361 | memoryKey: "history", // by default 362 | }); 363 | 364 | const chain = RunnableSequence.from([ 365 | /* 第一个 Map 用于透传原始输入和加载 Memory 对象 */ 366 | { 367 | input: (initialInput) => initialInput.input, 368 | memory: () => memory.loadMemoryVariables({}), 369 | }, 370 | /* 第二个 Map 用于继续透传原始输入和加载 Memory 的 history 部分数据 */ 371 | { 372 | input: (previousOutput) => previousOutput.input, 373 | history: (previousOutput) => previousOutput.memory.history, 374 | }, 375 | prompt, 376 | model, 377 | ]); 378 | 379 | const inputs = { input: "Hey, I'm Bob!" }; 380 | const response = await chain.invoke(inputs); 381 | 382 | /* 完成一次对话后进行 Memory 数据数据 */ 383 | await memory.saveContext(inputs, { output: response.content }); 384 | /* 385 | { 386 | history: [ 387 | HumanMessage { 388 | content: "Hey, I'm Bob!", 389 | additional_kwargs: {} 390 | }, 391 | AIMessage { 392 | content: " Hi Bob, nice to meet you! I'm Claude, an AI assistant created by Anthropic to be helpful, harmless, and honest.", 393 | additional_kwargs: {} 394 | } 395 | ] 396 | } 397 | */ 398 | 399 | const inputs2 = { input: "What's my name?" }; 400 | const response2 = await chain.invoke(inputs2); 401 | ``` 402 | 403 | --- 404 | level: 2 405 | --- 406 | 407 | # 为 Runnable Sequence 提供条件路由 408 | 409 | 路由允许您创建非确定性的 Chain,其中上一步的输出定义了下一步的路由方向 410 | 411 | 在 JS/TS 中可使用 [`RunnableBranch`](https://js.langchain.com/docs/expression_language/how_to/routing) 来构建条件路由,路由会依次匹配条件直至选择默认 Runnable 返回: 412 | 413 | ```ts {23-36|43-44|all} {maxHeight:'75%'} 414 | const langChainChain = PromptTemplate.fromTemplate( 415 | `You are an expert in langchain. Always answer questions starting with "As Harrison Chase told me". 416 | Respond to the following question: 417 | 418 | Question: {question} 419 | Answer:` 420 | ).pipe(model); 421 | 422 | const anthropicChain = PromptTemplate.fromTemplate( 423 | `You are an expert in anthropic. Always answer questions starting with "As Dario Amodei told me". 424 | Respond to the following question: 425 | 426 | Question: {question} 427 | Answer:` 428 | ).pipe(model); 429 | 430 | const generalChain = PromptTemplate.fromTemplate(`Respond to the following question: 431 | 432 | Question: {question} 433 | Answer:` 434 | ).pipe(model); 435 | 436 | /* 构建一个条件路由,依次选择 Anthropic -> LangChain -> General Chain */ 437 | const branch = RunnableBranch.from([ 438 | [ 439 | (x: { topic: string; question: string }) => 440 | x.topic.toLowerCase().includes("anthropic"), 441 | anthropicChain, 442 | ], 443 | [ 444 | (x: { topic: string; question: string }) => 445 | x.topic.toLowerCase().includes("langchain"), 446 | langChainChain, 447 | ], 448 | generalChain, 449 | ]); 450 | 451 | const fullChain = RunnableSequence.from([ 452 | { 453 | topic: classificationChain, 454 | question: (input: { question: string }) => input.question, 455 | }, 456 | /* 可以直接将路由串联进一个 Runnable Sequence 中 */ 457 | branch, 458 | ]); 459 | ``` 460 | 461 | --- 462 | level: 2 463 | --- 464 | 465 | # Runnable 的 Fallback 机制 466 | 467 | [Fallback](https://js.langchain.com/docs/guides/fallbacks) 机制可以提供优雅的异常处理,通过“以优充次”的方式尽可能保障链路执行继续执行 468 | 469 | 在 JS/TS 中,可使用 `runnable.withFallbacks({ fallbacks: [runnable] })` 来构建 Fallback 支撑 470 | 471 | ```ts 472 | const fakeOpenAIModel = new ChatOpenAI({ 473 | modelName: "potato!", // Fake model name will always throw an error 474 | maxRetries: 0, 475 | }); 476 | 477 | const modelWithFallback = fakeOpenAIModel.withFallbacks({ 478 | fallbacks: [new ChatAnthropic({})], 479 | }); 480 | ``` 481 | 482 | 不仅可以支撑 Runnable 对象,还可以直接 Fallback 整个 Runnable Sequence: 483 | 484 | ```ts 485 | const badChain = chatPrompt.pipe(fakeOpenAIChatModel).pipe(outputParser); 486 | const goodChain = prompt.pipe(openAILLM).pipe(outputParser); 487 | 488 | const chain = badChain.withFallbacks({ 489 | fallbacks: [goodChain], 490 | }); 491 | ``` 492 | 493 | --- 494 | layout: quote 495 | --- 496 | 497 | # Chains 498 | 499 | LangChain 为“链式”应用提供了 Chain 接口 500 | 501 | --- 502 | level: 2 503 | --- 504 | 505 | # 链路调试的“文韬武略” 506 | 507 | 除了接入强力的 LangSmith,也可以使用 Console 输出调试信息 508 | 509 | 和调试 Runnable Sequence 一样,首选的调试方式肯定还是接入 LangSmith,有两种方式: 510 | 511 | ```sh 512 | export LANGCHAIN_TRACING_V2=true 513 | export LANGCHAIN_ENDPOINT=https://api.smith.langchain.com 514 | export LANGCHAIN_API_KEY= # still in closed beta 515 | export LANGCHAIN_PROJECT= # if not specified, defaults to "default" 516 | ``` 517 | ```ts {4-} 518 | import { Client } from "langsmith"; 519 | import { LangChainTracer } from "langchain/callbacks"; 520 | 521 | const client = new Client({ apiUrl: "https://api.smith.langchain.com", apiKey: "YOUR_API_KEY" }); 522 | const tracer = new LangChainTracer({ projectName: "YOUR_PROJECT_NAME", client }); 523 | 524 | await model.invoke("Hello, world!", { callbacks: [tracer] }) 525 | ``` 526 | 527 | 退而求其次,可以开启 `verbose` 选项,有两种方式: 528 | 529 | ```sh 530 | export LANGCHAIN_VERBOSE=true 531 | ``` 532 | ```ts 533 | const chain = new ConversationChain({ llm: chat, verbose: true }); 534 | ``` 535 | 536 | --- 537 | level: 2 538 | --- 539 | 540 | # 一条链路贯天地 541 | 542 | 类似 Runnable Sequence 的链路构建,但相比之下 [Sequential](https://js.langchain.com/docs/modules/chains/foundational/sequential_chains) 操作的复杂度更加高 543 | 544 | - `SimpleSequentialChain`:最简单形式,每个步骤都有单个输入/输出,一个步骤的输出是下一个的输入 545 | - `SequentialChain`:顺序链的更通用形式,允许多个输入/输出 546 | 547 | ```ts {12-13,21-22|24-|all} {maxHeight:'70%'} 548 | import { SequentialChain, LLMChain } from "langchain/chains"; 549 | import { OpenAI } from "langchain/llms/openai"; 550 | import { PromptTemplate } from "langchain/prompts"; 551 | 552 | // This is an LLMChain to write a synopsis given a title of a play and the era it is set in. 553 | const llm = new OpenAI({ temperature: 0 }); 554 | const template = `You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title. 555 | 556 | Title: {title} 557 | Era: {era} 558 | Playwright: This is a synopsis for the above play:`; 559 | const promptTemplate = new PromptTemplate({template, inputVariables: ["title", "era"] }); 560 | const synopsisChain = new LLMChain({ llm, prompt: promptTemplate, outputKey: "synopsis" }); 561 | 562 | // This is an LLMChain to write a review of a play given a synopsis. 563 | const reviewTemplate = `You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play. 564 | 565 | Play Synopsis: 566 | {synopsis} 567 | Review from a New York Times play critic of the above play:`; 568 | const reviewPromptTemplate = new PromptTemplate({ template: reviewTemplate, inputVariables: ["synopsis"] }); 569 | const reviewChain = new LLMChain({ llm, prompt: reviewPromptTemplate, outputKey: "review" }); 570 | 571 | const overallChain = new SequentialChain({ 572 | chains: [synopsisChain, reviewChain], // 串联两个 LLMChain 573 | inputVariables: ["era", "title"], // 定义需要传入的变量 574 | outputVariables: ["synopsis", "review"], // 定义需要输出的变量 575 | }); 576 | const chainExecutionResult = await overallChain.call({ title: "Tragedy at sunset on the beach", era: "Victorian England" }); 577 | ``` 578 | 579 | --- 580 | layout: iframe 581 | url: https://smith.langchain.com/public/63376249-1360-4cea-9886-da72b3abbfd4/r 582 | --- 583 | 584 | --- 585 | level: 2 586 | --- 587 | 588 | # 两类模型舞前沿 589 | 590 | 最基础的链式调用是 [`LLMChain`](https://js.langchain.com/docs/modules/chains/foundational/llm_chain),它同时支持 LLM 和 Chat 模型 591 | 592 | ```ts 593 | /* 构建基于 LLM 模型的 LLMChain */ 594 | const model = new OpenAI({ temperature: 0 }); 595 | const prompt = PromptTemplate.fromTemplate("What is a good name for a company that makes {product}?"); 596 | const chainA = new LLMChain({ llm: model, prompt }); 597 | 598 | // 通过 .call(object) 返回输出对象 599 | const resA = await chainA.call({ product: "colorful socks" }); // { text: '\n\nSocktastic!' } 600 | // 通过 .run(string) 返回输出字符串 601 | const resA2 = await chainA.run("colorful socks"); // '\n\nSocktastic!' 602 | ``` 603 |
604 | 605 | ```ts 606 | /* 构建基于 Chat 模型的 LLMChain */ 607 | const chat = new ChatOpenAI({ temperature: 0 }); 608 | const chatPrompt = ChatPromptTemplate.fromMessages([ 609 | ["system", "You are a helpful assistant that translates {input_language} to {output_language}."], 610 | ["human", "{text}"], 611 | ]); 612 | const chainB = new LLMChain({ prompt: chatPrompt, llm: chat }); 613 | 614 | const resB = await chainB.call({ input_language: "English", output_language: "French", text: "I love programming." }); 615 | // { text: "J'adore la programmation." } 616 | ``` 617 | 618 | --- 619 | level: 2 620 | --- 621 | 622 | # 三种巧思治文档 623 | 624 | LangChain 提供处理文档的工具链,它们对于总结文档、回答文档问题、从文档中提取信息等很有用 625 | 626 | [三种文档处理工具链](https://js.langchain.com/docs/modules/chains/document/) 的使用方式基本是一样的,如下所示: 627 | 628 | ```ts {10-} 629 | import { OpenAI } from "langchain/llms/openai"; 630 | import { loadQAStuffChain, loadQAMapReduceChain } from "langchain/chains"; 631 | import { Document } from "langchain/document"; 632 | 633 | const docs = [ 634 | new Document({ pageContent: "Harrison went to Harvard." }), 635 | new Document({ pageContent: "Ankush went to Princeton." }), 636 | ]; 637 | 638 | /* 构建并使用 StuffDocumentsChain */ 639 | const llmA = new OpenAI({}); 640 | const chainA = loadQAStuffChain(llmA); 641 | const resA = await chainA.call({ input_documents: docs, question: "Where did Harrison go to college?" }); 642 | 643 | /* 构建并使用 MapReduceChain */ 644 | const llmB = new OpenAI({ maxConcurrency: 10 }); 645 | const chainB = loadQAMapReduceChain(llmB); 646 | const resB = await chainB.call({ input_documents: docs, question: "Where did Harrison go to college?" }); 647 | ``` 648 | 649 | --- 650 | level: 3 651 | --- 652 | 653 | 654 | 655 | 656 | --- 657 | level: 3 658 | --- 659 | 660 | # 层叠递进的 Refine 模式 661 | 662 | - 对于每个文档,它将所有非文档输入、当前文档以及最新的中间答案传递给 LLM 链以获得新的答案 663 | - 由于 Refine 链一次仅将单个文档传递给 LLM,因此很适合需要分析的文档数量多于模型上下文的任务 664 | - 明显的缺点是:将比 Stuff 文档链进行更多的 LLM 调用;当文档频繁地互相交叉引用时很可能表现不佳 665 | 666 | ![](https://js.langchain.com/assets/images/refine-a70f30dd7ada6fe5e3fcc40dd70de037.jpg) 667 | 668 | --- 669 | level: 3 670 | --- 671 | 672 | # 🌰 Refine 文档链的二阶段提示词应用 673 | 674 | ```ts {8-18|20-34|36-39|all} {maxHeight:'90%'} 675 | import { loadQARefineChain } from "langchain/chains"; 676 | import { OpenAI } from "langchain/llms/openai"; 677 | import { TextLoader } from "langchain/document_loaders/fs/text"; 678 | import { MemoryVectorStore } from "langchain/vectorstores/memory"; 679 | import { OpenAIEmbeddings } from "langchain/embeddings/openai"; 680 | import { PromptTemplate } from "langchain/prompts"; 681 | 682 | /* 最终提问时使用的提示词 */ 683 | export const questionPromptTemplateString = `Context information is below. 684 | --------------------- 685 | {context} 686 | --------------------- 687 | Given the context information and no prior knowledge, answer the question: {question}`; 688 | 689 | const questionPrompt = new PromptTemplate({ 690 | inputVariables: ["context", "question"], 691 | template: questionPromptTemplateString, 692 | }); 693 | 694 | /* 中间 Refine 过程使用的提示词 */ 695 | const refinePromptTemplateString = `The original question is as follows: {question} 696 | We have provided an existing answer: {existing_answer} 697 | We have the opportunity to refine the existing answer 698 | (only if needed) with some more context below. 699 | ------------ 700 | {context} 701 | ------------ 702 | Given the new context, refine the original answer to better answer the question. 703 | You must provide a response, either original answer or refined answer.`; 704 | 705 | const refinePrompt = new PromptTemplate({ 706 | inputVariables: ["question", "existing_answer", "context"], 707 | template: refinePromptTemplateString, 708 | }); 709 | 710 | /* 构建 Refine 文档链,并导入两份提示词模板 */ 711 | const embeddings = new OpenAIEmbeddings(); 712 | const model = new OpenAI({ temperature: 0 }); 713 | const chain = loadQARefineChain(model, { questionPrompt, refinePrompt }); 714 | 715 | // Load the documents and create the vector store 716 | const loader = new TextLoader("./state_of_the_union.txt"); 717 | const docs = await loader.loadAndSplit(); 718 | const store = await MemoryVectorStore.fromDocuments(docs, embeddings); 719 | 720 | // Select the relevant documents 721 | const question = "What did the president say about Justice Breyer"; 722 | const relevantDocs = await store.similaritySearch(question); 723 | 724 | const res = await chain.call({ input_documents: relevantDocs, question }); 725 | ``` 726 | 727 | --- 728 | level: 2 729 | --- 730 | 731 | # 四套应用疏通途:Retrieval QA 732 | 733 | [Retrieval QA Chain](https://js.langchain.com/docs/modules/chains/popular/vector_db_qa) 通过从检索器检索文档,然后使用文档工具链,根据检索到的文档回答问题 734 | 735 | ```ts {18-22|24-|all} {maxHeight:'85%'} 736 | import { OpenAI } from "langchain/llms/openai"; 737 | import { RetrievalQAChain, loadQAStuffChain } from "langchain/chains"; 738 | import { HNSWLib } from "langchain/vectorstores/hnswlib"; 739 | import { OpenAIEmbeddings } from "langchain/embeddings/openai"; 740 | import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; 741 | import { PromptTemplate } from "langchain/prompts"; 742 | import * as fs from "fs"; 743 | 744 | const promptTemplate = `Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. 745 | 746 | {context} 747 | 748 | Question: {question} 749 | Answer in Italian:`; 750 | const prompt = PromptTemplate.fromTemplate(promptTemplate); 751 | const model = new OpenAI({}); 752 | 753 | /* 构建文档检索器 */ 754 | const text = fs.readFileSync("state_of_the_union.txt", "utf8"); 755 | const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 }); 756 | const docs = await textSplitter.createDocuments([text]); 757 | const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings()); 758 | 759 | /* 构建基于 Stuff 文档链和自定义提示词的 Retrieval QA Chain */ 760 | const chain = new RetrievalQAChain({ 761 | combineDocumentsChain: loadQAStuffChain(model, { prompt }), 762 | retriever: vectorStore.asRetriever(), 763 | returnSourceDocuments: true, // 要求一并返回原始文档 764 | }); 765 | const res = await chain.call({ query: "What did the president say about Justice Breyer?" }); 766 | ``` 767 | 768 | --- 769 | level: 2 770 | --- 771 | 772 | # 四套应用疏通途:Conversational Retrieval QA 773 | 774 | [Conversational Retrieval QA Chain](https://js.langchain.com/docs/modules/chains/popular/chat_vector_db) 建立在 Retrieval QA Chain 的基础上,并接入 Memory 组件 775 | 776 | 它首先将聊天历史记录和问题组合成一个独立的问题,然后将检索得到的文档和问题传递给问答链以返回响应 777 | 778 | ```ts {35-49|51-|all} {maxHeight:'75%'} 779 | import { ChatOpenAI } from "langchain/chat_models/openai"; 780 | import { ConversationalRetrievalQAChain } from "langchain/chains"; 781 | import { HNSWLib } from "langchain/vectorstores/hnswlib"; 782 | import { OpenAIEmbeddings } from "langchain/embeddings/openai"; 783 | import { BufferMemory } from "langchain/memory"; 784 | 785 | const CUSTOM_QUESTION_GENERATOR_CHAIN_PROMPT = `Given the following conversation and a follow up question, return the conversation history excerpt that includes any relevant context to the question if it exists and rephrase the follow up question to be a standalone question. 786 | Chat History: 787 | {chat_history} 788 | Follow Up Input: {question} 789 | Your answer should follow the following format: 790 | \`\`\` 791 | Use the following pieces of context to answer the users question. 792 | If you don't know the answer, just say that you don't know, don't try to make up an answer. 793 | ---------------- 794 | 795 | Standalone question: 796 | \`\`\` 797 | Your answer:`; 798 | 799 | const model = new ChatOpenAI({ temperature: 0 }); 800 | 801 | const vectorStore = await HNSWLib.fromTexts( 802 | [ 803 | "Mitochondria are the powerhouse of the cell", 804 | "Foo is red", 805 | "Bar is red", 806 | "Buildings are made out of brick", 807 | "Mitochondria are made of lipids", 808 | ], 809 | [{ id: 2 }, { id: 1 }, { id: 3 }, { id: 4 }, { id: 5 }], 810 | new OpenAIEmbeddings() 811 | ); 812 | 813 | /* 构建 Conversational Retrieval QA Chain */ 814 | const chain = ConversationalRetrievalQAChain.fromLLM( 815 | model, 816 | vectorStore.asRetriever(), 817 | /* 导入 Memory 和自定义提示词模板 */ 818 | { 819 | memory: new BufferMemory({ 820 | memoryKey: "chat_history", 821 | returnMessages: true, 822 | }), 823 | questionGeneratorChainOptions: { 824 | template: CUSTOM_QUESTION_GENERATOR_CHAIN_PROMPT, 825 | }, 826 | } 827 | ); 828 | 829 | const res1 = await chain.call({ question: "I have a friend called Bob. He's 28 years old. He'd like to know what the powerhouse of the cell is?" }); 830 | // { text: "The powerhouse of the cell is the mitochondria." } 831 | 832 | const res2 = await chain.call({ question: "How old is Bob?" }); 833 | // { text: "Bob is 28 years old." } 834 | ``` 835 | 836 | --- 837 | layout: iframe 838 | url: https://smith.langchain.com/public/517b2110-349f-4089-8051-9b5203e34c0b/r 839 | --- 840 | 841 | --- 842 | layout: iframe 843 | url: https://smith.langchain.com/public/69a66e55-e00d-4aae-9953-8e42f4feaeea/r 844 | --- 845 | 846 | --- 847 | level: 2 848 | --- 849 | 850 | # 四套应用疏通途:SQL QA 851 | 852 | 利用 LLM 的 SQL 生成能力,可以构建 [SQL Chain](https://js.langchain.com/docs/modules/chains/popular/sqlite) 来进行面向数据库的问答 853 | 854 | ```ts {24-26|28-36|all} {maxHeight:'80%'} 855 | import { DataSource } from "typeorm"; 856 | import { OpenAI } from "langchain/llms/openai"; 857 | import { SqlDatabase } from "langchain/sql_db"; 858 | import { SqlDatabaseChain } from "langchain/chains/sql_db"; 859 | import { PromptTemplate } from "langchain/prompts"; 860 | 861 | const template = `Given an input question, first create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer. 862 | Use the following format: 863 | 864 | Question: "Question here" 865 | SQLQuery: "SQL Query to run" 866 | SQLResult: "Result of the SQLQuery" 867 | Answer: "Final answer here" 868 | 869 | Only use the following tables: 870 | 871 | {table_info} 872 | 873 | If someone asks for the table foobar, they really mean the employee table. 874 | 875 | Question: {input}`; 876 | const prompt = PromptTemplate.fromTemplate(template); 877 | 878 | /* 构建数据库连接 */ 879 | const appDataSource = new DataSource({ type: "sqlite", database: "data/Chinook.db" }); 880 | const db = await SqlDatabase.fromDataSourceParams({ appDataSource }); 881 | 882 | /* 构建并执行 SQL QA Chain */ 883 | const chain = new SqlDatabaseChain({ 884 | llm: new OpenAI({ temperature: 0 }), 885 | database: db, 886 | sqlOutputKey: "sql", // 要求返回 SQL 语句 887 | prompt, // 使用自定义提示词 888 | }); 889 | await chain.call({ query: "How many employees are there in the foobar table?" }); 890 | /* 891 | { 892 | result: ' There are 8 employees in the foobar table.', 893 | sql: ' SELECT COUNT(*) FROM Employee;' 894 | } 895 | */ 896 | ``` 897 | 898 | --- 899 | layout: iframe 900 | url: https://smith.langchain.com/public/89aaa750-4115-4ad0-a987-39ea0b2e52f4/r 901 | --- 902 | 903 | --- 904 | level: 3 905 | --- 906 | 907 | # 用 Runnable Sequence 实现 SQL QA 908 | 909 | ```ts {38-51} {maxHeight:'90%'} 910 | import { DataSource } from "typeorm"; 911 | import { SqlDatabase } from "langchain/sql_db"; 912 | import { RunnableSequence } from "langchain/schema/runnable"; 913 | import { PromptTemplate } from "langchain/prompts"; 914 | import { StringOutputParser } from "langchain/schema/output_parser"; 915 | import { ChatOpenAI } from "langchain/chat_models/openai"; 916 | 917 | const datasource = new DataSource({ type: "sqlite", database: "Chinook.db" }); 918 | const db = await SqlDatabase.fromDataSourceParams({ appDataSource: datasource }); 919 | 920 | const prompt = 921 | PromptTemplate.fromTemplate(`Based on the table schema below, write a SQL query that would answer the user's question: 922 | {schema} 923 | 924 | Question: {question} 925 | SQL Query:`); 926 | 927 | const model = new ChatOpenAI(); 928 | 929 | const sqlQueryGeneratorChain = RunnableSequence.from([ 930 | { 931 | schema: async () => db.getTableInfo(), 932 | question: (input: { question: string }) => input.question, 933 | }, 934 | prompt, 935 | model.bind({ stop: ["\nSQLResult:"] }), 936 | new StringOutputParser(), 937 | ]); 938 | 939 | const finalResponsePrompt = 940 | PromptTemplate.fromTemplate(`Based on the table schema below, question, sql query, and sql response, write a natural language response: 941 | {schema} 942 | 943 | Question: {question} 944 | SQL Query: {query} 945 | SQL Response: {response}`); 946 | 947 | const fullChain = RunnableSequence.from([ 948 | { 949 | question: (input) => input.question, 950 | query: sqlQueryGeneratorChain, 951 | }, 952 | { 953 | schema: async () => db.getTableInfo(), 954 | question: (input) => input.question, 955 | query: (input) => input.query, 956 | response: (input) => db.run(input.query), 957 | }, 958 | finalResponsePrompt, 959 | model, 960 | ]); 961 | 962 | const finalResponse = await fullChain.invoke({ question: "How many employees are there?" }); 963 | ``` 964 | 965 | --- 966 | layout: iframe 967 | url: https://smith.langchain.com/public/6d79dcfb-e501-45f5-ad31-0d605233627b/r 968 | --- 969 | 970 | --- 971 | level: 2 972 | --- 973 | 974 | # 四套应用疏通途:Web API 975 | 976 | [API Chain](https://js.langchain.com/docs/modules/chains/popular/api) 允许使用 LLM 与 API 交互以检索相关信息,通过提供与提供的 API 文档相关的问题来构建链 977 | 978 | ```ts {34-} {maxHeight:'90%'} 979 | import { OpenAI } from "langchain/llms/openai"; 980 | import { APIChain } from "langchain/chains"; 981 | 982 | const OPEN_METEO_DOCS = `BASE URL: https://api.open-meteo.com/ 983 | 984 | API Documentation 985 | The API endpoint /v1/forecast accepts a geographical coordinate, a list of weather variables and responds with a JSON hourly weather forecast for 7 days. Time always starts at 0:00 today and contains 168 hours. All URL parameters are listed below: 986 | 987 | Parameter Format Required Default Description 988 | latitude, longitude Floating point Yes Geographical WGS84 coordinate of the location 989 | hourly String array No A list of weather variables which should be returned. Values can be comma separated, or multiple &hourly= parameter in the URL can be used. 990 | daily String array No A list of daily weather variable aggregations which should be returned. Values can be comma separated, or multiple &daily= parameter in the URL can be used. If daily weather variables are specified, parameter timezone is required. 991 | current_weather Bool No false Include current weather conditions in the JSON output. 992 | temperature_unit String No celsius If fahrenheit is set, all temperature values are converted to Fahrenheit. 993 | windspeed_unit String No kmh Other wind speed speed units: ms, mph and kn 994 | precipitation_unit String No mm Other precipitation amount units: inch 995 | timeformat String No iso8601 If format unixtime is selected, all time values are returned in UNIX epoch time in seconds. Please note that all timestamp are in GMT+0! For daily values with unix timestamps, please apply utc_offset_seconds again to get the correct date. 996 | timezone String No GMT If timezone is set, all timestamps are returned as local-time and data is returned starting at 00:00 local-time. Any time zone name from the time zone database is supported. If auto is set as a time zone, the coordinates will be automatically resolved to the local time zone. 997 | past_days Integer (0-2) No 0 If past_days is set, yesterday or the day before yesterday data are also returned. 998 | start_date 999 | end_date String (yyyy-mm-dd) No The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30). 1000 | models String array No auto Manually select one or more weather models. Per default, the best suitable weather models will be combined. 1001 | 1002 | Variable Valid time Unit Description 1003 | temperature_2m Instant °C (°F) Air temperature at 2 meters above ground 1004 | snowfall Preceding hour sum cm (inch) Snowfall amount of the preceding hour in centimeters. For the water equivalent in millimeter, divide by 7. E.g. 7 cm snow = 10 mm precipitation water equivalent 1005 | rain Preceding hour sum mm (inch) Rain from large scale weather systems of the preceding hour in millimeter 1006 | showers Preceding hour sum mm (inch) Showers from convective precipitation in millimeters from the preceding hour 1007 | weathercode Instant WMO code Weather condition as a numeric code. Follow WMO weather interpretation codes. See table below for details. 1008 | snow_depth Instant meters Snow depth on the ground 1009 | freezinglevel_height Instant meters Altitude above sea level of the 0°C level 1010 | visibility Instant meters Viewing distance in meters. Influenced by low clouds, humidity and aerosols. Maximum visibility is approximately 24 km.`; 1011 | 1012 | const model = new OpenAI({ modelName: "text-davinci-003" }); 1013 | const chain = APIChain.fromLLMAndAPIDocs(model, OPEN_METEO_DOCS, { headers: {} }); 1014 | await chain.call({ question: "What is the weather like right now in Munich, Germany in degrees Farenheit?" }); 1015 | ``` 1016 | 1017 | --- 1018 | layout: iframe 1019 | url: https://smith.langchain.com/public/8d7555a1-66bc-4f03-843e-261a4f576f4d/r 1020 | --- 1021 | 1022 | --- 1023 | level: 2 1024 | --- 1025 | 1026 | # 种类繁多的“预制菜” 1027 | 1028 | 相比 Runnable Sequence 的自定义能力强,Chain 的最大特点就是预制化程度高 1029 | 1030 | > 下面以 JS/TS SDK 展示一些有特色的 Chain 1031 | 1032 |
1033 | 1034 | - 基于 [OpenAI Functions](https://platform.openai.com/docs/guides/gpt/function-calling) 能力底座的 Chain: 1035 | - [`createExtractionChainFromZod`](https://js.langchain.com/docs/modules/chains/additional/openai_functions/extraction):从输入文本和所需信息的模式中提取对象列表 1036 | - [`createTaggingChain`](https://js.langchain.com/docs/modules/chains/additional/openai_functions/tagging):根据模式中定义的属性来标记输入文本 1037 | - [`createOpenAPIChain`](https://js.langchain.com/docs/modules/chains/additional/openai_functions/openapi):基于 Open API 规范自动选择和调用 API 1038 | - [`OpenAIModerationChain`](https://js.langchain.com/docs/modules/chains/additional/moderation):审核链基于 OpenAI Moderation 对于检测可能仇恨、暴力等的文本很有用 1039 | - [`ConstitutionalChain`](https://js.langchain.com/docs/modules/chains/additional/constitutional_chain):自我批判链是一条确保语言模型的输出遵守一组预定义准则的链 1040 | 1041 | 此外,也提供用于条件路由的 Chain: 1042 | - [`MultiPromptChain`](https://js.langchain.com/docs/modules/chains/additional/multi_prompt_router):使用多提示链创建一个问答链,选择与给定问题最相关的提示并进行回答 1043 | - [`MultiRetrievalQAChain`](https://js.langchain.com/docs/modules/chains/additional/multi_retrieval_qa_router):该链选择与给定问题最相关的 Retrieval QA Chain,然后使用它回答问题 1044 | 1045 | --- 1046 | src: ../../pages/common/refs.md 1047 | --- 1048 | 1049 | --- 1050 | src: ../../pages/common/end.md 1051 | --- 1052 | -------------------------------------------------------------------------------- /203-langchain-agents/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /203-langchain-agents/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /203-langchain-agents/ --out ../../dist/203-langchain-agents", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/203-langchain-agents.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.43.6", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /203-langchain-agents/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/203-langchain-agents.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shiki' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # LangChain 模块解析(下) 33 | 34 | LangChain Agents and Callbacks Hands-on 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | src: ../../pages/common/series.md 59 | --- 60 | 61 | --- 62 | src: ../../pages/common/toc.md 63 | --- 64 | 65 | --- 66 | 67 | # Agent vs. Chain 68 | 69 | 如果说 Agent 是 Chain 的进化形态,那哪些方面是对等的?哪些地方又存在质变? 70 | 71 | ➡️ Agent 继承了 Chain 的所有能力 72 | 73 | - Chain 的能力构成了 Agent 的 “推理链” 能力基础 74 | - Agent 的执行器(Executor)就是基于 LLM Chain 实现的 75 | - Agent 自身具备和 Chain 类似的 “调用 / 执行” 接口的能力 76 | 77 |
78 | 79 | ⬆️⬆️ Agent 在 Chain 的能力基础上进化出了两个核心能力 80 | 81 | - 一条思考链Chain of Thought):Agent 可以规划和调度推理链,会思考分步骤的、每一步的行动 82 | - 一个工具箱(Toolbox):Agent 自带工具体系,可以接入并调用外部工具(工具可以按既定接口规范定制) 83 | - Agent 只关注每个工具的输入输出(格式及内容),工具内部可以自行进行本地和 Web 接口调用 84 | 85 | --- 86 | 87 | # Agent 的思考链模式:ReAct 88 | 89 | [ReAct](https://react-lm.github.io/): Synergizing Reasoning and Acting in Language Models 90 | 91 | ![](https://react-lm.github.io/files/diagram.png) 92 | 93 | ReAct 使用大语言模型同时生成推理链和行动,两者交替出现,相互支持: 94 | - 推理链帮助 Agent 制定、跟踪和更新行动计划 95 | - 行动让 Agent 与环境上下文交互,获取更多信息支持推理 96 | 97 | ♻️流程概览:给出任务 ➡️ 推理下一步行动 ➡️ 行动并更新环境 ➡️ 观察并推理下一步行动 ➡️ 循环直至任务完成 98 | 99 | --- 100 | level: 2 101 | --- 102 | 103 | # 🌰 使用 ReAct 模式的 Agent 104 | 105 | ```ts {7-16|18-21|all} {maxHeight:'90%'} 106 | import { initializeAgentExecutorWithOptions } from "langchain/agents"; 107 | import { OpenAI } from "langchain/llms/openai"; 108 | import { SerpAPI } from "langchain/tools"; 109 | import { Calculator } from "langchain/tools/calculator"; 110 | 111 | const model = new OpenAI({ temperature: 0 }); 112 | const tools = [ 113 | /* Web 搜索工具 */ 114 | new SerpAPI(process.env.SERPAPI_API_KEY, { 115 | location: "Austin,Texas,United States", 116 | hl: "en", 117 | gl: "us", 118 | }), 119 | /* 本地计算器工具 */ 120 | new Calculator(), 121 | ]; 122 | 123 | const executor = await initializeAgentExecutorWithOptions(tools, model, { 124 | agentType: "zero-shot-react-description", 125 | verbose: true, 126 | }); 127 | 128 | const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; 129 | const result = await executor.call({ input }); 130 | ``` 131 | 132 | --- 133 | layout: iframe 134 | url: https://smith.langchain.com/public/99f09caa-d6e4-4424-a8cd-7daa02ee5e13/r 135 | --- 136 | 137 | --- 138 | level: 2 139 | --- 140 | 141 | # ReAct 模式的核心提示词 142 | 143 | ```ts 144 | export const PREFIX = `Answer the following questions as best you can. You have access to the following tools:`; 145 | 146 | export const FORMAT_INSTRUCTIONS = `Use the following format in your response: 147 | 148 | Question: the input question you must answer 149 | Thought: you should always think about what to do 150 | Action: the action to take, should be one of [{tool_names}] 151 | Action Input: the input to the action 152 | Observation: the result of the action 153 | ... (this Thought/Action/Action Input/Observation can repeat N times) 154 | Thought: I now know the final answer 155 | Final Answer: the final answer to the original input question`; 156 | 157 | export const SUFFIX = `Begin! 158 | 159 | Question: {input} 160 | Thought:{agent_scratchpad}`; 161 | ``` 162 | 163 | ```ts 164 | const executor = await initializeAgentExecutorWithOptions(tools, chat, { 165 | agentType: "", 166 | agentArgs: { prefix, suffix }, // 可自定义前置和后置提示词 167 | }); 168 | ``` 169 | 170 | --- 171 | 172 | # Agent 的思考链模式:Plan and Execute 173 | 174 | [Plan-and-Solve Prompting](https://arxiv.org/pdf/2305.04091.pdf): Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models 175 | 176 | 顾名思义,Agent 通过首先计划要做什么,然后执行子任务来实现目标 177 | 178 | - 这个想法很大程度上是受到 [BabyAGI](https://github.com/yoheinakajima/babyagi) 和后来的《Plan-and-Solve Prompting》论文的启发 179 | - 计划几乎总是由 LLM 完成;执行通常由单独的(带有工具的)Agent 完成 180 | 181 |
182 | 183 | 该 Agent 有两个主要的关键步骤: 184 | 185 | 1. 首先,Agent 使用 LLM 创建一个计划,以明确的步骤回答查询 186 | 2. 一旦制定了计划,它就会使用传统的 Agent(比如 ReAct)来解决每个步骤 187 | 188 |
189 | 190 | > 其想法是,计划步骤通过将较大的任务分解为更简单的子任务,使 LLM 更加“步入正轨”。 191 | > 192 | > 但是,与传统 Agent 相比,此方法需要更多单独的 LLM 查询,并且延迟更高。 193 | 194 | --- 195 | level: 2 196 | --- 197 | 198 | # 🌰 使用 Plan and Execute 模式的 Agent 199 | 200 | 该模式的 Agent 目前仅支持 Chat 模型 201 | 202 | ```ts {13-16|all} 203 | import { Calculator } from "langchain/tools/calculator"; 204 | import { SerpAPI } from "langchain/tools"; 205 | import { ChatOpenAI } from "langchain/chat_models/openai"; 206 | import { PlanAndExecuteAgentExecutor } from "langchain/experimental/plan_and_execute"; 207 | 208 | const tools = [new Calculator(), new SerpAPI()]; 209 | const model = new ChatOpenAI({ 210 | temperature: 0, 211 | modelName: "gpt-3.5-turbo", 212 | verbose: true, 213 | }); 214 | 215 | const executor = PlanAndExecuteAgentExecutor.fromLLMAndTools({ 216 | llm: model, 217 | tools, 218 | }); 219 | 220 | const result = await executor.call({ 221 | input: `Who is the current president of the United States? What is their current age raised to the second power?`, 222 | }); 223 | ``` 224 | 225 | --- 226 | layout: iframe 227 | url: https://smith.langchain.com/public/33110a27-032f-4d6d-a121-4063931d189b/r 228 | --- 229 | 230 | --- 231 | level: 2 232 | --- 233 | 234 | # Plan and Execute 模式的核心提示词 235 | 236 | ```ts 237 | export const PLANNER_SYSTEM_PROMPT_MESSAGE_TEMPLATE = [ 238 | `Let's first understand the problem and devise a plan to solve the problem.`, 239 | `Please output the plan starting with the header "Plan:"`, 240 | `and then followed by a numbered list of steps.`, 241 | `Please make the plan the minimum number of steps required`, 242 | `to answer the query or complete the task accurately and precisely.`, 243 | `Your steps should be general, and should not require a specific method to solve a step. If the task is a question,`, 244 | `the final step in the plan must be the following: "Given the above steps taken,`, 245 | `please respond to the original query."`, 246 | `At the end of your plan, say ""`, 247 | ].join(" "); 248 | 249 | export const DEFAULT_STEP_EXECUTOR_HUMAN_CHAT_MESSAGE_TEMPLATE = `Previous steps: {previous_steps} 250 | 251 | Current objective: {current_step} 252 | 253 | {agent_scratchpad} 254 | 255 | You may extract and combine relevant data from your previous steps when responding to me.`; 256 | ``` 257 | 258 | --- 259 | 260 | # ReAct 模式的工具能力强化:JSON Schema 261 | 262 | 工具的输入输出限定为单个字符串 ➡️ 可以使用工具提供的 JSON Schema 接口定义来扩展输入输出 263 | 264 | ```ts {10-20|23-25|all} {maxHeight:'85%'} 265 | import { z } from "zod"; 266 | import { ChatOpenAI } from "langchain/chat_models/openai"; 267 | import { initializeAgentExecutorWithOptions } from "langchain/agents"; 268 | import { Calculator } from "langchain/tools/calculator"; 269 | import { DynamicStructuredTool } from "langchain/tools"; 270 | 271 | const model = new ChatOpenAI({ temperature: 0 }); 272 | const tools = [ 273 | new Calculator(), // Older existing single input tools will still work 274 | new DynamicStructuredTool({ 275 | name: "random-number-generator", 276 | description: "generates a random number between two input numbers", 277 | schema: z.object({ 278 | low: z.number().describe("The lower bound of the generated number"), 279 | high: z.number().describe("The upper bound of the generated number"), 280 | }), 281 | func: async ({ low, high }) => 282 | (Math.random() * (high - low) + low).toString(), // Outputs still must be strings 283 | returnDirect: false, // This is an option that allows the tool to return the output directly 284 | }), 285 | ]; 286 | 287 | const executor = await initializeAgentExecutorWithOptions(tools, model, { 288 | agentType: "structured-chat-zero-shot-react-description", 289 | }); 290 | 291 | const input = `What is a random number between 5 and 10 raised to the second power?`; 292 | const result = await executor.call({ input }); 293 | ``` 294 | 295 | --- 296 | layout: iframe 297 | url: https://smith.langchain.com/public/1b23a713-58e3-42f8-93db-60fa99cb1207/r 298 | --- 299 | 300 | --- 301 | 302 | # ReAct 模式的工具能力强化:OpenAI Functions 303 | 304 | OpenAI 模型(如 `gpt-3.5-turbo-0613`)已经过微调,可以检测何时应调用函数并响应应传递给函数的输入 305 | 306 | - OpenAI Functions 的目标是比通用文本完成或聊天 API 更可靠地返回有效且有用的函数调用 307 | - 在 API 调用中,您可以描述函数并让模型智能地选择输出包含调用这些函数的参数的 JSON 对象 308 | 309 | ```ts 310 | import { initializeAgentExecutorWithOptions } from "langchain/agents"; 311 | import { ChatOpenAI } from "langchain/chat_models/openai"; 312 | import { SerpAPI } from "langchain/tools"; 313 | import { Calculator } from "langchain/tools/calculator"; 314 | 315 | const tools = [new Calculator(), new SerpAPI()]; 316 | const chat = new ChatOpenAI({ modelName: "gpt-4", temperature: 0 }); 317 | 318 | const executor = await initializeAgentExecutorWithOptions(tools, chat, { 319 | agentType: "openai-functions", 320 | verbose: true, 321 | }); 322 | 323 | const result = await executor.run("What is the weather in New York?"); 324 | ``` 325 | 326 | --- 327 | layout: iframe 328 | url: https://smith.langchain.com/public/f81e509f-9a51-4f0b-9554-4b351cd8ebdb/r 329 | --- 330 | 331 | --- 332 | 333 | # ReAct 模式下的 XML Agent 334 | 335 | 某些语言模型(例如 [Anthropic](https://www.anthropic.com/) 的 Claude)特别擅长推理/编写 XML 336 | 337 | ```ts 338 | import { ChatAnthropic } from "langchain/chat_models/anthropic"; 339 | import { initializeAgentExecutorWithOptions } from "langchain/agents"; 340 | import { SerpAPI } from "langchain/tools"; 341 | 342 | const model = new ChatAnthropic({ modelName: "claude-2", temperature: 0.1 }); 343 | const tools = [new SerpAPI()]; 344 | 345 | const executor = await initializeAgentExecutorWithOptions(tools, model, { 346 | agentType: "xml", 347 | verbose: true, 348 | }); 349 | console.log("Loaded agent."); 350 | 351 | const input = `What is the weather in Honolulu?`; 352 | const result = await executor.call({ input }); 353 | ``` 354 | 355 | --- 356 | layout: iframe 357 | url: https://smith.langchain.com/public/d0acd50a-f99d-4af0-ae66-9009de319fb5/r 358 | --- 359 | 360 | --- 361 | 362 | # Agent 的工具箱 363 | 364 | 工具是 Agent 可以用来与世界交互的功能 365 | 366 | Agent 只关心工具的输入输出,内部实现对 Agent 透明 367 | 368 | - 这些工具可以是通用实用程序(例如搜索)、其它 Chain 调用,甚至其它 Agent 调用 369 | 370 |
371 | 372 | Agent 定义了工具的标准接口,以实现无缝集成 373 | 374 | - 具体来说,工具的接口具有单个文本输入和单个文本输出 375 | - 它包括名称和描述,用于向模型传达该工具的用途以及何时使用它 376 | 377 | ```ts 378 | abstract class Tool { 379 | abstract name: string; 380 | abstract description: string; 381 | 382 | abstract _call(arg: string): Promise; 383 | } 384 | ``` 385 | 386 | --- 387 | level: 2 388 | --- 389 | 390 | # 🌰 Calculator 工具的实现 391 | 392 | ```ts {all|9-12|1,17|all} 393 | import { Parser } from "expr-eval"; 394 | import { Tool } from "./base.js"; 395 | 396 | /** 397 | * The Calculator class is a tool used to evaluate mathematical 398 | * expressions. It extends the base Tool class. 399 | */ 400 | export class Calculator extends Tool { 401 | name = "calculator"; 402 | 403 | description = `Useful for getting the result of a math expression. 404 | The input to this tool should be a valid mathematical expression that could be executed by a simple calculator.`; 405 | 406 | /** @ignore */ 407 | async _call(input: string) { 408 | try { 409 | return Parser.evaluate(input).toString(); 410 | } catch (error) { 411 | return "I don't know how to do that."; 412 | } 413 | } 414 | } 415 | ``` 416 | 417 | --- 418 | level: 2 419 | --- 420 | 421 | # Tool 的结构化输入定义 422 | 423 | Tool 可以通过 JSON Schema 来强化输入的定义,在 JS/TS SDK 中会使用 Zod 转换 TypeScript 类型声明 424 | 425 | 如下所示,SerpAPI 工具中对参数接口进行了详细的定义: 426 | 427 | ```ts {all} {maxHeight:'80%'} 428 | // Copied over from `serpapi` package 429 | interface BaseParameters { 430 | /** 431 | * Parameter defines the device to use to get the results. It can be set to 432 | * `desktop` (default) to use a regular browser, `tablet` to use a tablet browser 433 | * (currently using iPads), or `mobile` to use a mobile browser (currently 434 | * using iPhones). 435 | */ 436 | device?: "desktop" | "tablet" | "mobile"; 437 | /** 438 | * Parameter will force SerpApi to fetch the Google results even if a cached 439 | * version is already present. A cache is served only if the query and all 440 | * parameters are exactly the same. Cache expires after 1h. Cached searches 441 | * are free, and are not counted towards your searches per month. It can be set 442 | * to `false` (default) to allow results from the cache, or `true` to disallow 443 | * results from the cache. `no_cache` and `async` parameters should not be used together. 444 | */ 445 | no_cache?: boolean; 446 | /** 447 | * Specify the client-side timeout of the request. In milliseconds. 448 | */ 449 | timeout?: number; 450 | } 451 | 452 | export interface SerpAPIParameters extends BaseParameters { 453 | /** 454 | * Search Query 455 | * Parameter defines the query you want to search. You can use anything that you 456 | * would use in a regular Google search. e.g. `inurl:`, `site:`, `intitle:`. We 457 | * also support advanced search query parameters such as as_dt and as_eq. See the 458 | * [full list](https://serpapi.com/advanced-google-query-parameters) of supported 459 | * advanced search query parameters. 460 | */ 461 | q: string; 462 | /** 463 | * Location 464 | * Parameter defines from where you want the search to originate. If several 465 | * locations match the location requested, we'll pick the most popular one. Head to 466 | * [/locations.json API](https://serpapi.com/locations-api) if you need more 467 | * precise control. location and uule parameters can't be used together. Avoid 468 | * utilizing location when setting the location outside the U.S. when using Google 469 | * Shopping and/or Google Product API. 470 | */ 471 | location?: string; 472 | /** 473 | * Encoded Location 474 | * Parameter is the Google encoded location you want to use for the search. uule 475 | * and location parameters can't be used together. 476 | */ 477 | uule?: string; 478 | /** 479 | * Google Place ID 480 | * Parameter defines the id (`CID`) of the Google My Business listing you want to 481 | * scrape. Also known as Google Place ID. 482 | */ 483 | ludocid?: string; 484 | /** 485 | * Additional Google Place ID 486 | * Parameter that you might have to use to force the knowledge graph map view to 487 | * show up. You can find the lsig ID by using our [Local Pack 488 | * API](https://serpapi.com/local-pack) or [Places Results 489 | * API](https://serpapi.com/places-results). 490 | * lsig ID is also available via a redirect Google uses within [Google My 491 | * Business](https://www.google.com/business/). 492 | */ 493 | lsig?: string; 494 | /** 495 | * Google Knowledge Graph ID 496 | * Parameter defines the id (`KGMID`) of the Google Knowledge Graph listing you 497 | * want to scrape. Also known as Google Knowledge Graph ID. Searches with kgmid 498 | * parameter will return results for the originally encrypted search parameters. 499 | * For some searches, kgmid may override all other parameters except start, and num 500 | * parameters. 501 | */ 502 | kgmid?: string; 503 | /** 504 | * Google Cached Search Parameters ID 505 | * Parameter defines the cached search parameters of the Google Search you want to 506 | * scrape. Searches with si parameter will return results for the originally 507 | * encrypted search parameters. For some searches, si may override all other 508 | * parameters except start, and num parameters. si can be used to scrape Google 509 | * Knowledge Graph Tabs. 510 | */ 511 | si?: string; 512 | /** 513 | * Domain 514 | * Parameter defines the Google domain to use. It defaults to `google.com`. Head to 515 | * the [Google domains page](https://serpapi.com/google-domains) for a full list of 516 | * supported Google domains. 517 | */ 518 | google_domain?: string; 519 | /** 520 | * Country 521 | * Parameter defines the country to use for the Google search. It's a two-letter 522 | * country code. (e.g., `us` for the United States, `uk` for United Kingdom, or 523 | * `fr` for France). Head to the [Google countries 524 | * page](https://serpapi.com/google-countries) for a full list of supported Google 525 | * countries. 526 | */ 527 | gl?: string; 528 | /** 529 | * Language 530 | * Parameter defines the language to use for the Google search. It's a two-letter 531 | * language code. (e.g., `en` for English, `es` for Spanish, or `fr` for French). 532 | * Head to the [Google languages page](https://serpapi.com/google-languages) for a 533 | * full list of supported Google languages. 534 | */ 535 | hl?: string; 536 | /** 537 | * Set Multiple Languages 538 | * Parameter defines one or multiple languages to limit the search to. It uses 539 | * `lang_{two-letter language code}` to specify languages and `|` as a delimiter. 540 | * (e.g., `lang_fr|lang_de` will only search French and German pages). Head to the 541 | * [Google lr languages page](https://serpapi.com/google-lr-languages) for a full 542 | * list of supported languages. 543 | */ 544 | lr?: string; 545 | /** 546 | * as_dt 547 | * Parameter controls whether to include or exclude results from the site named in 548 | * the as_sitesearch parameter. 549 | */ 550 | as_dt?: string; 551 | /** 552 | * as_epq 553 | * Parameter identifies a phrase that all documents in the search results must 554 | * contain. You can also use the [phrase 555 | * search](https://developers.google.com/custom-search/docs/xml_results#PhraseSearchqt) 556 | * query term to search for a phrase. 557 | */ 558 | as_epq?: string; 559 | /** 560 | * as_eq 561 | * Parameter identifies a word or phrase that should not appear in any documents in 562 | * the search results. You can also use the [exclude 563 | * query](https://developers.google.com/custom-search/docs/xml_results#Excludeqt) 564 | * term to ensure that a particular word or phrase will not appear in the documents 565 | * in a set of search results. 566 | */ 567 | as_eq?: string; 568 | /** 569 | * as_lq 570 | * Parameter specifies that all search results should contain a link to a 571 | * particular URL. You can also use the 572 | * [link:](https://developers.google.com/custom-search/docs/xml_results#BackLinksqt) 573 | * query term for this type of query. 574 | */ 575 | as_lq?: string; 576 | /** 577 | * as_nlo 578 | * Parameter specifies the starting value for a search range. Use as_nlo and as_nhi 579 | * to append an inclusive search range. 580 | */ 581 | as_nlo?: string; 582 | /** 583 | * as_nhi 584 | * Parameter specifies the ending value for a search range. Use as_nlo and as_nhi 585 | * to append an inclusive search range. 586 | */ 587 | as_nhi?: string; 588 | /** 589 | * as_oq 590 | * Parameter provides additional search terms to check for in a document, where 591 | * each document in the search results must contain at least one of the additional 592 | * search terms. You can also use the [Boolean 593 | * OR](https://developers.google.com/custom-search/docs/xml_results#BooleanOrqt) 594 | * query term for this type of query. 595 | */ 596 | as_oq?: string; 597 | /** 598 | * as_q 599 | * Parameter provides search terms to check for in a document. This parameter is 600 | * also commonly used to allow users to specify additional terms to search for 601 | * within a set of search results. 602 | */ 603 | as_q?: string; 604 | /** 605 | * as_qdr 606 | * Parameter requests search results from a specified time period (quick date 607 | * range). The following values are supported: 608 | * `d[number]`: requests results from the specified number of past days. Example 609 | * for the past 10 days: `as_qdr=d10` 610 | * `w[number]`: requests results from the specified number of past weeks. 611 | * `m[number]`: requests results from the specified number of past months. 612 | * `y[number]`: requests results from the specified number of past years. Example 613 | * for the past year: `as_qdr=y` 614 | */ 615 | as_qdr?: string; 616 | /** 617 | * as_rq 618 | * Parameter specifies that all search results should be pages that are related to 619 | * the specified URL. The parameter value should be a URL. You can also use the 620 | * [related:](https://developers.google.com/custom-search/docs/xml_results#RelatedLinksqt) 621 | * query term for this type of query. 622 | */ 623 | as_rq?: string; 624 | /** 625 | * as_sitesearch 626 | * Parameter allows you to specify that all search results should be pages from a 627 | * given site. By setting the as_dt parameter, you can also use it to exclude pages 628 | * from a given site from your search resutls. 629 | */ 630 | as_sitesearch?: string; 631 | /** 632 | * Advanced Search Parameters 633 | * (to be searched) parameter defines advanced search parameters that aren't 634 | * possible in the regular query field. (e.g., advanced search for patents, dates, 635 | * news, videos, images, apps, or text contents). 636 | */ 637 | tbs?: string; 638 | /** 639 | * Adult Content Filtering 640 | * Parameter defines the level of filtering for adult content. It can be set to 641 | * `active`, or `off` (default). 642 | */ 643 | safe?: string; 644 | /** 645 | * Exclude Auto-corrected Results 646 | * Parameter defines the exclusion of results from an auto-corrected query that is 647 | * spelled wrong. It can be set to `1` to exclude these results, or `0` to include 648 | * them (default). 649 | */ 650 | nfpr?: string; 651 | /** 652 | * Results Filtering 653 | * Parameter defines if the filters for 'Similar Results' and 'Omitted Results' are 654 | * on or off. It can be set to `1` (default) to enable these filters, or `0` to 655 | * disable these filters. 656 | */ 657 | filter?: string; 658 | /** 659 | * Search Type 660 | * (to be matched) parameter defines the type of search you want to do. 661 | * It can be set to: 662 | * `(no tbm parameter)`: regular Google Search, 663 | * `isch`: [Google Images API](https://serpapi.com/images-results), 664 | * `lcl` - [Google Local API](https://serpapi.com/local-results) 665 | * `vid`: [Google Videos API](https://serpapi.com/videos-results), 666 | * `nws`: [Google News API](https://serpapi.com/news-results), 667 | * `shop`: [Google Shopping API](https://serpapi.com/shopping-results), 668 | * or any other Google service. 669 | */ 670 | tbm?: string; 671 | /** 672 | * Result Offset 673 | * Parameter defines the result offset. It skips the given number of results. It's 674 | * used for pagination. (e.g., `0` (default) is the first page of results, `10` is 675 | * the 2nd page of results, `20` is the 3rd page of results, etc.). 676 | * Google Local Results only accepts multiples of `20`(e.g. `20` for the second 677 | * page results, `40` for the third page results, etc.) as the start value. 678 | */ 679 | start?: number; 680 | /** 681 | * Number of Results 682 | * Parameter defines the maximum number of results to return. (e.g., `10` (default) 683 | * returns 10 results, `40` returns 40 results, and `100` returns 100 results). 684 | */ 685 | num?: string; 686 | /** 687 | * Page Number (images) 688 | * Parameter defines the page number for [Google 689 | * Images](https://serpapi.com/images-results). There are 100 images per page. This 690 | * parameter is equivalent to start (offset) = ijn * 100. This parameter works only 691 | * for [Google Images](https://serpapi.com/images-results) (set tbm to `isch`). 692 | */ 693 | ijn?: string; 694 | } 695 | ``` 696 | 697 | --- 698 | 699 | # Agent 工具箱中的工具集 700 | 701 | 工具集(Toolkit)是旨在一起用于特定任务并具有方便的加载方法的工具的集合 702 | 703 | ```ts 704 | const toolkit = new JsonToolkit(new JsonSpec(data)); 705 | const model = new OpenAI({ temperature: 0 }); 706 | const executor = createJsonAgent(model, toolkit); 707 | ``` 708 | 709 | 值得注意的是,为了更好地串联工具,工具集一般会重新定义 ReAct Agent 的部分提示词 710 | 711 | ```ts {all} {maxHeight:'55%'} 712 | export const JSON_PREFIX = `You are an agent designed to interact with JSON. 713 | Your goal is to return a final answer by interacting with the JSON. 714 | You have access to the following tools which help you learn more about the JSON you are interacting with. 715 | Only use the below tools. Only use the information returned by the below tools to construct your final answer. 716 | Do not make up any information that is not contained in the JSON. 717 | Your input to the tools should be in the form of in json pointer syntax (e.g. /key1/0/key2). 718 | You must escape a slash in a key with a ~1, and escape a tilde with a ~0. 719 | For example, to access the key /foo, you would use /~1foo 720 | You should only use keys that you know for a fact exist. You must validate that a key exists by seeing it previously when calling 'json_list_keys'. 721 | If you have not seen a key in one of those responses, you cannot use it. 722 | You should only add one key at a time to the path. You cannot add multiple keys at once. 723 | If you encounter a null or undefined value, go back to the previous key, look at the available keys, and try again. 724 | 725 | If the question does not seem to be related to the JSON, just return "I don't know" as the answer. 726 | Always begin your interaction with the 'json_list_keys' with an empty string as the input to see what keys exist in the JSON. 727 | 728 | Note that sometimes the value at a given path is large. In this case, you will get an error "Value is a large dictionary, should explore its keys directly". 729 | In this case, you should ALWAYS follow up by using the 'json_list_keys' tool to see what keys exist at that path. 730 | Do not simply refer the user to the JSON or a section of the JSON, as this is not a valid answer. Keep digging until you find the answer and explicitly return it.`; 731 | 732 | export const JSON_SUFFIX = `Begin!" 733 | 734 | Question: {input} 735 | Thought: I should look at the keys that exist to see what I can query. I should use the 'json_list_keys' tool with an empty string as the input. 736 | {agent_scratchpad}`; 737 | ``` 738 | 739 | --- 740 | layout: iframe 741 | url: https://smith.langchain.com/public/e173ea9a-eb25-45bb-93c9-edf4d3bab6b0/r 742 | --- 743 | 744 | --- 745 | level: 2 746 | --- 747 | 748 | # 🌰 Web API 调用:OpenAPI Agent 749 | 750 | 如下所示,我们会通过 OpenAPI Agent 来调用 OpenAI 的文本补全接口(参见 [完整接口文件](https://github.com/langchain-ai/langchainjs/blob/main/examples/openai_openapi.yaml)) 751 | 752 | ```ts 753 | const headers = { 754 | "Content-Type": "application/json", 755 | Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, 756 | }; 757 | const model = new OpenAI({ temperature: 0 }); 758 | const toolkit = new OpenApiToolkit(new JsonSpec(data), model, headers); 759 | const executor = createOpenApiAgent(model, toolkit); 760 | ``` 761 | ```ts {all} {maxHeight:'50%'} 762 | export const OPENAPI_PREFIX = `You are an agent designed to answer questions by making web requests to an API given the OpenAPI spec. 763 | 764 | If the question does not seem related to the API, return I don't know. Do not make up an answer. 765 | Only use information provided by the tools to construct your response. 766 | 767 | To find information in the OpenAPI spec, use the 'json_explorer' tool. The input to this tool is a question about the API. 768 | 769 | Take the following steps: 770 | First, find the base URL needed to make the request. 771 | 772 | Second, find the relevant paths needed to answer the question. Take note that, sometimes, you might need to make more than one request to more than one path to answer the question. 773 | 774 | Third, find the required parameters needed to make the request. For GET requests, these are usually URL parameters and for POST requests, these are request body parameters. 775 | 776 | Fourth, make the requests needed to answer the question. Ensure that you are sending the correct parameters to the request by checking which parameters are required. For parameters with a fixed set of values, please use the spec to look at which values are allowed. 777 | 778 | Use the exact parameter names as listed in the spec, do not make up any names or abbreviate the names of parameters. 779 | If you get a not found error, ensure that you are using a path that actually exists in the spec.`; 780 | 781 | export const OPENAPI_SUFFIX = `Begin!" 782 | 783 | Question: {input} 784 | Thought: I should explore the spec to find the base url for the API. 785 | {agent_scratchpad}`; 786 | export const JSON_EXPLORER_DESCRIPTION = ` 787 | Can be used to answer questions about the openapi spec for the API. Always use this tool before trying to make a request. 788 | Example inputs to this tool: 789 | 'What are the required query parameters for a GET request to the /bar endpoint?' 790 | 'What are the required parameters in the request body for a POST request to the /foo endpoint?' 791 | Always give this tool a specific question.`; 792 | ``` 793 | 794 | --- 795 | layout: iframe 796 | url: https://smith.langchain.com/public/23fde4a9-e601-4d3b-93b7-152ed2dd6e9e/r 797 | --- 798 | 799 | --- 800 | layout: iframe 801 | url: https://smith.langchain.com/public/7466ecfb-6bc7-47de-b1e4-b7d386578c0e/r 802 | --- 803 | 804 | --- 805 | layout: iframe 806 | url: https://smith.langchain.com/public/719fb342-b90b-4ca2-b721-2fa4cf2497b5/r 807 | --- 808 | 809 | --- 810 | layout: iframe 811 | url: https://smith.langchain.com/public/c165d036-f363-4041-a652-8ade7b0893e4/r 812 | --- 813 | 814 | --- 815 | level: 2 816 | --- 817 | 818 | # 🌰 向量存储也可以作用工具(集) 819 | 820 | ```ts {16-} {maxHeight:'90%'} 821 | import { OpenAI } from "langchain/llms/openai"; 822 | import { HNSWLib } from "langchain/vectorstores/hnswlib"; 823 | import { OpenAIEmbeddings } from "langchain/embeddings/openai"; 824 | import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; 825 | import { VectorStoreToolkit, createVectorStoreAgent, VectorStoreInfo } from "langchain/agents"; 826 | 827 | const model = new OpenAI({ temperature: 0 }); 828 | /* Load in the file we want to do question answering over */ 829 | const text = fs.readFileSync("state_of_the_union.txt", "utf8"); 830 | /* Split the text into chunks using character, not token, size */ 831 | const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 }); 832 | const docs = await textSplitter.createDocuments([text]); 833 | /* Create the vectorstore */ 834 | const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings()); 835 | 836 | /* Create the agent */ 837 | const vectorStoreInfo: VectorStoreInfo = { 838 | name: "state_of_union_address", 839 | description: "the most recent state of the Union address", 840 | vectorStore, 841 | }; 842 | 843 | const toolkit = new VectorStoreToolkit(vectorStoreInfo, model); 844 | const agent = createVectorStoreAgent(model, toolkit); 845 | 846 | const input = "What did biden say about Ketanji Brown Jackson is the state of the union address?"; 847 | const result = await agent.call({ input }); 848 | ``` 849 | 850 | --- 851 | layout: iframe 852 | url: https://smith.langchain.com/public/6b91b7c9-4eaa-48ae-a883-0b6a7794d707/r 853 | --- 854 | 855 | --- 856 | 857 | # 必不可缺的 Callback 回调系统 858 | 859 | Callback 回调系统让我们可以连接到 LLM 应用的各个阶段,这对于日志记录、监控、流传输等非常有用 860 | 861 | `callbacks` 参数在整个 API(Model、Chain、Agent、Tool 等)的大多数对象上的两个不同位置可用 862 | 863 | - 可以在构造器位置上接入 Callback(但不能跨对象使用),以 JS/TS 中的 Model 为例: 864 | 865 | ```ts 866 | import { ConsoleCallbackHandler } from "langchain/callbacks"; 867 | 868 | const llm = new OpenAI({ 869 | // These tags will be attached to all calls made with this LLM. 870 | tags: ["example", "callbacks", "constructor"], 871 | // This handler will be used for all calls made with this LLM. 872 | callbacks: [new ConsoleCallbackHandler()], 873 | }); 874 | ``` 875 | 876 | - 也可以在模块对象的 `apply()` / `run()` / `call()` 实例方法中发起请求时绑定,但仅对该请求有效: 877 | 878 | ```ts 879 | const llm = new OpenAI({ temperature: 0 }); 880 | const response = await llm.call("1 + 1 =", { 881 | // These tags will be attached only to this call to the LLM. 882 | tags: ["example", "callbacks", "request"], 883 | // This handler will be used only for this call. 884 | callbacks: [new ConsoleCallbackHandler()], 885 | }); 886 | ``` 887 | 888 | --- 889 | level: 2 890 | --- 891 | 892 | # 回顾:链路调试的“文韬武略” 893 | 894 | 我们既可以接入强力的 LangSmith,也可以使用 Console 输出调试信息 895 | 896 | 如何获得足够多且跨模块对象 Console 调试信息 ➡️ 开启 `verbose` 选项: 897 | 898 | ```sh 899 | export LANGCHAIN_VERBOSE=true 900 | ``` 901 | ```ts 902 | const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: "xml", verbose: true }); 903 | ``` 904 | 905 | 或者直接通过环境变量接入 LangSmith: 906 | 907 | ```sh 908 | export LANGCHAIN_TRACING_V2=true 909 | export LANGCHAIN_ENDPOINT=https://api.smith.langchain.com 910 | export LANGCHAIN_API_KEY= # still in closed beta 911 | export LANGCHAIN_PROJECT= # if not specified, defaults to "default" 912 | ``` 913 | 914 | ⚠️ 以下方式只能用于对象构造器和对象请求,不能形成完整链路: 915 | 916 | ```ts {4-} 917 | import { Client } from "langsmith"; 918 | import { LangChainTracer } from "langchain/callbacks"; 919 | 920 | const client = new Client({ apiUrl: "https://api.smith.langchain.com", apiKey: "YOUR_API_KEY" }); 921 | const tracer = new LangChainTracer({ projectName: "YOUR_PROJECT_NAME", client }); 922 | ``` 923 | 924 | --- 925 | level: 2 926 | --- 927 | 928 | # 如何自定义 Callback 处理器 929 | 930 | LangChain 支持通过实现基本回调处理程序接口来创建您自己的处理程序 931 | 932 | 自定义 Callback Handler 可以做一些比输出调试信息到控制台更复杂的事情,例如将事件发送到日志记录服务。作为示例,这里是一个记录到控制台的处理程序的 JS/TS 版本简单实现: 933 | 934 | ```ts {4-} {maxHeight:'70%'} 935 | import { BaseCallbackHandler } from "langchain/callbacks"; 936 | import { Serialized } from "langchain/load/serializable"; 937 | import { AgentAction, AgentFinish, ChainValues } from "langchain/schema"; 938 | 939 | export class MyCallbackHandler extends BaseCallbackHandler { 940 | name = "MyCallbackHandler"; 941 | 942 | async handleChainStart(chain: Serialized) { 943 | console.log(`Entering new ${chain.id} chain...`); 944 | } 945 | 946 | async handleChainEnd(_output: ChainValues) { 947 | console.log("Finished chain."); 948 | } 949 | 950 | async handleAgentAction(action: AgentAction) { 951 | console.log(action.log); 952 | } 953 | 954 | async handleToolEnd(output: string) { 955 | console.log(output); 956 | } 957 | 958 | async handleText(text: string) { 959 | console.log(text); 960 | } 961 | 962 | async handleAgentEnd(action: AgentFinish) { 963 | console.log(action.log); 964 | } 965 | } 966 | ``` 967 | 968 | --- 969 | src: ../../pages/common/refs.md 970 | --- 971 | 972 | --- 973 | src: ../../pages/common/end.md 974 | --- -------------------------------------------------------------------------------- /240106-langchain-status/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "slidev", 5 | "build": "slidev build --base /240106-langchain-status/ --out ../../dist/240106-langchain-status", 6 | "export": "slidev export --dark --timeout 0 --output ../../pdfs/240106-langchain-status.pdf" 7 | }, 8 | "devDependencies": { 9 | "@slidev/cli": "^0.46.1", 10 | "@slidev/theme-seriph": "^0.21.3" 11 | }, 12 | "slidev": { 13 | "addons": [ 14 | "../../addons/webup" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /240106-langchain-status/src/slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | # See all frontmatter configurations: https://sli.dev/custom/#frontmatter-configures 3 | # theme id or package name, see also: https://sli.dev/themes/use.html 4 | theme: 'seriph' 5 | # titleTemplate for the webpage, `%s` will be replaced by the page's title 6 | titleTemplate: '%s|WebUP' 7 | # some information about the slides, markdown enabled 8 | info: | 9 | AGI 学习笔记,仅供个人学习使用 10 | # favicon, can be a local file path or URL 11 | favicon: https://files.codelife.cc/user-website-icon/20220523/5hyKeZxOknU2owAPvnSWD1388.png?x-oss-process=image/resize,limit_0,m_fill,w_25,h_25/quality,q_92/format,webp 12 | # enabled pdf downloading in SPA build, can also be a custom url 13 | download: 'https://github.com/webup/agi-talks/raw/master/pdfs/240106-langchain-status.pdf' 14 | # syntax highlighter, can be 'prism' or 'shiki' 15 | highlighter: 'shikiji' 16 | # controls whether texts in slides are selectable 17 | selectable: false 18 | # enable slide recording, can be boolean, 'dev' or 'build' 19 | record: 'build' 20 | # define transition between slides 21 | transition: fade 22 | # default frontmatter applies to all slides 23 | defaults: 24 | 25 | # slide configurations 26 | hideInToc: true 27 | layout: cover 28 | class: text-center 29 | background: https://source.unsplash.com/collection/94734566/1920x1080 30 | --- 31 | 32 | # LangChain 生态综述 33 | 34 | LangChain Ecosystem Walkthrough 35 | 36 |
37 | 38 | Press Space for next page 39 | 40 |
41 | 42 | 56 | 57 | --- 58 | hideInToc: true 59 | layout: intro 60 | --- 61 | 62 | # 张海立 63 | 64 |
65 | KubeSphere Ambassador, CNCF OpenFunction TOC Member
66 | 驭势科技 UISEE© 云平台研发总监,开源爱好者
67 | 云原生专注领域: Kubernetes, DevOps, FaaS, Observability
68 | AGI 专注领域:LangChain, RAG, Prompt Engineering, GenAI
69 |
70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
81 | 82 | 83 | 84 | --- 85 | layout: quote 86 | --- 87 | 88 | # 🗺️ 开局一张图 89 | 90 | 从 LangChain 生态全景(架构)图说起 91 | 92 | --- 93 | layout: iframe 94 | url: https://python.langchain.com/docs/get_started/introduction 95 | --- 96 | 97 | --- 98 | layout: iframe-right 99 | url: https://blog.langchain.dev/the-new-langchain-architecture-langchain-core-v0-1-langchain-community-and-a-path-to-langchain-v0-1/ 100 | --- 101 | 102 | # 🦜️🔗 LangChain 类库 103 | 104 | 定位:本地构建 LLM 原型应用 105 | 106 | - langchain-core 包含了核心抽象和 [LangChain Expression Language](https://python.langchain.com/docs/expression_language/)(LCEL) 107 | - 版本已经达到 0.1, 未来的任何破坏性变更都会带来小版本升级(0.x) 108 | - 模块化的抽象为第三方集成提供标准接口 109 | - langchain-community 包含 [第三方集成](https://python.langchain.com/docs/integrations/providers) 110 | - 主要集成将被进一步拆分为独立软件包 111 | - 目前,LangChain 拥有近 700 个集成 112 | - langchain 包含了实际运用的 Chain、Agent 和 Retriever 流程策略 113 | - 官方计划 1/9 推出 0.1 稳定版本 114 | 115 | --- 116 | layout: iframe 117 | url: https://integrations.langchain.com/ 118 | --- 119 | 120 | --- 121 | layout: iframe-right 122 | url: https://blog.langchain.dev/langchain-templates/ 123 | --- 124 | 125 | # 🦜️🔗 LangChain 模板 126 | 127 | 定位:提供预制的可参考的 LLM 原型应用 128 | 129 | 通常配合 LangServe 一起使用(三步走): 130 | 131 | 1️⃣ 安装 `langchain-cli` 132 | 133 | ```sh 134 | pip install -U langchain-cli 135 | ``` 136 | 137 | 2️⃣ (创建新项目)导入指定模版 138 | 139 | ```sh 140 | langchain app new my-app --package $PACKAGE_NAME 141 | langchain app add $PACKAGE_NAME 142 | # adding custom GitHub repo packages 143 | langchain app add --repo $OWNER/$REPO 144 | ``` 145 | 146 | 3️⃣ 绑定 LangServe 服务端点(`server.py`) 147 | 148 | ```py 149 | add_routes(app, chain, path="/chain-path") 150 | ``` 151 | 152 | 🚀 启动!`langchain serve` 153 | 154 | --- 155 | layout: iframe 156 | url: https://templates.langchain.com/ 157 | --- 158 | 159 | --- 160 | layout: iframe-right 161 | url: https://blog.langchain.dev/introducing-langserve/ 162 | --- 163 | 164 | # 🦜️🏓 LangServe 类库 165 | 166 | 定位:一键 REST 服务化 LLM 原型应用 167 | 168 | 169 | 170 | --- 171 | layout: iframe-right 172 | url: https://blog.langchain.dev/announcing-langsmith/ 173 | --- 174 | 175 | # 🦜️⚒️ LangSmith 平台 176 | 177 | 定位:提供全生命周期的可观测能力 178 | 179 |