├── Alpaca meets Langchain.ipynb ├── Chat-with-Flang20B-LangChain-HuggingFace.ipynb ├── ChatGPT🤝LangChain🔥.ipynb ├── Conversations-with-Memory.ipynb ├── HuggingFaceHub🤝LangChain-Work-Local.ipynb ├── LLM-Prompting-Basics.ipynb ├── PAL-Chain-of-Thought-Modeling.ipynb ├── README.md └── The-First-Sequential-Chain.ipynb /Alpaca meets Langchain.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# !pip -q install git+https://github.com/huggingface/transformers # need to install from github\n", 10 | "# !pip install -q datasets loralib sentencepiece \n", 11 | "# !pip -q install bitsandbytes accelerate\n", 12 | "# !pip -q install langchain" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "### We can use LangChain - HuggingFacePipeline to wrap the custom LLMs. but this only support text2text-generation, text-generation pipelines" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 11, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "import torch, warnings\n", 29 | "from langchain.llms import HuggingFacePipeline\n", 30 | "from langchain.chains import ConversationChain\n", 31 | "from langchain import PromptTemplate, LLMChain\n", 32 | "from transformers import LlamaTokenizer, LlamaForCausalLM, GenerationConfig, pipeline, BitsAndBytesConfig\n", 33 | "from langchain.chains.conversation.memory import ConversationBufferWindowMemory\n", 34 | "warnings.filterwarnings(\"ignore\")" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "#### 1. download alpaca natives" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 2, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "name": "stdout", 51 | "output_type": "stream", 52 | "text": [ 53 | "\n", 54 | "===================================BUG REPORT===================================\n", 55 | "Welcome to bitsandbytes. For bug reports, please run\n", 56 | "\n", 57 | "python -m bitsandbytes\n", 58 | "\n", 59 | " and submit this information together with your error trace to: https://github.com/TimDettmers/bitsandbytes/issues\n", 60 | "================================================================================\n", 61 | "bin /home/ec2-user/anaconda3/envs/pytorch_p39/lib/python3.9/site-packages/bitsandbytes/libbitsandbytes_cuda117_nocublaslt.so\n", 62 | "CUDA SETUP: CUDA runtime path found: /home/ec2-user/anaconda3/envs/pytorch_p39/lib/libcudart.so\n", 63 | "CUDA SETUP: Highest compute capability among GPUs detected: 7.0\n", 64 | "CUDA SETUP: Detected CUDA version 117\n", 65 | "CUDA SETUP: Loading binary /home/ec2-user/anaconda3/envs/pytorch_p39/lib/python3.9/site-packages/bitsandbytes/libbitsandbytes_cuda117_nocublaslt.so...\n" 66 | ] 67 | }, 68 | { 69 | "name": "stderr", 70 | "output_type": "stream", 71 | "text": [ 72 | "The model weights are not tied. Please use the `tie_weights` method before using the `infer_auto_device` function.\n" 73 | ] 74 | }, 75 | { 76 | "data": { 77 | "application/json": { 78 | "ascii": false, 79 | "bar_format": null, 80 | "colour": null, 81 | "elapsed": 0.010372638702392578, 82 | "initial": 0, 83 | "n": 0, 84 | "ncols": null, 85 | "nrows": null, 86 | "postfix": null, 87 | "prefix": "Loading checkpoint shards", 88 | "rate": null, 89 | "total": 3, 90 | "unit": "it", 91 | "unit_divisor": 1000, 92 | "unit_scale": false 93 | }, 94 | "application/vnd.jupyter.widget-view+json": { 95 | "model_id": "701c4a6b1d0c4fdb9652ec1730d7410c", 96 | "version_major": 2, 97 | "version_minor": 0 98 | }, 99 | "text/plain": [ 100 | "Loading checkpoint shards: 0%| | 0/3 [00:00 Entering new ConversationChain chain...\u001b[0m\n", 312 | "Prompt after formatting:\n", 313 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 314 | " \n", 315 | "Current conversation:\n", 316 | "\n", 317 | "Human: Hi there! I am Isuru\n", 318 | "AI:\u001b[0m\n", 319 | "\n", 320 | "\u001b[1m> Finished chain.\u001b[0m\n" 321 | ] 322 | }, 323 | { 324 | "data": { 325 | "text/plain": [ 326 | "\" Hey there! It's nice to meet you too. What can I help you with?\"" 327 | ] 328 | }, 329 | "execution_count": 16, 330 | "metadata": {}, 331 | "output_type": "execute_result" 332 | } 333 | ], 334 | "source": [ 335 | "conversation.predict(input=\"Hi there! I am Isuru\")" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": 17, 341 | "metadata": {}, 342 | "outputs": [ 343 | { 344 | "name": "stdout", 345 | "output_type": "stream", 346 | "text": [ 347 | "\n", 348 | "\n", 349 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 350 | "Prompt after formatting:\n", 351 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 352 | " \n", 353 | "Current conversation:\n", 354 | "Human: Hi there! I am Isuru\n", 355 | "AI: Hey there! It's nice to meet you too. What can I help you with?\n", 356 | "Human: What is your name?\n", 357 | "AI:\u001b[0m\n", 358 | "\n", 359 | "\u001b[1m> Finished chain.\u001b[0m\n" 360 | ] 361 | }, 362 | { 363 | "data": { 364 | "text/plain": [ 365 | "' My name is Alpaca. How did you come up with that name?'" 366 | ] 367 | }, 368 | "execution_count": 17, 369 | "metadata": {}, 370 | "output_type": "execute_result" 371 | } 372 | ], 373 | "source": [ 374 | "conversation.predict(input=\"What is your name?\")" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 18, 380 | "metadata": {}, 381 | "outputs": [ 382 | { 383 | "name": "stdout", 384 | "output_type": "stream", 385 | "text": [ 386 | "\n", 387 | "\n", 388 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 389 | "Prompt after formatting:\n", 390 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 391 | " \n", 392 | "Current conversation:\n", 393 | "Human: Hi there! I am Isuru\n", 394 | "AI: Hey there! It's nice to meet you too. What can I help you with?\n", 395 | "Human: What is your name?\n", 396 | "AI: My name is Alpaca. How did you come up with that name?\n", 397 | "Human: Can you tell me what an Alpaca is?\n", 398 | "AI:\u001b[0m\n", 399 | "\n", 400 | "\u001b[1m> Finished chain.\u001b[0m\n" 401 | ] 402 | }, 403 | { 404 | "data": { 405 | "text/plain": [ 406 | "' Sure. An alpaca is a species of South American camelid mammal. They are typically found in the Andes mountains and live in herds led by an alpha female leader.'" 407 | ] 408 | }, 409 | "execution_count": 18, 410 | "metadata": {}, 411 | "output_type": "execute_result" 412 | } 413 | ], 414 | "source": [ 415 | "conversation.predict(input=\"Can you tell me what an Alpaca is?\")" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 19, 421 | "metadata": {}, 422 | "outputs": [ 423 | { 424 | "name": "stdout", 425 | "output_type": "stream", 426 | "text": [ 427 | "\n", 428 | "\n", 429 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 430 | "Prompt after formatting:\n", 431 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 432 | " \n", 433 | "Current conversation:\n", 434 | "Human: Hi there! I am Isuru\n", 435 | "AI: Hey there! It's nice to meet you too. What can I help you with?\n", 436 | "Human: What is your name?\n", 437 | "AI: My name is Alpaca. How did you come up with that name?\n", 438 | "Human: Can you tell me what an Alpaca is?\n", 439 | "AI: Sure. An alpaca is a species of South American camelid mammal. They are typically found in the Andes mountains and live in herds led by an alpha female leader.\n", 440 | "Human: How is it different from a Llama?\n", 441 | "AI:\u001b[0m\n", 442 | "\n", 443 | "\u001b[1m> Finished chain.\u001b[0m\n" 444 | ] 445 | }, 446 | { 447 | "data": { 448 | "text/plain": [ 449 | "' Alpacas and llamas belong to the same family but they have some differences as well. Alpacas tend to be smaller than llamas and they lack the long ear frills that llamas have. Additionally, their fleece is finer'" 450 | ] 451 | }, 452 | "execution_count": 19, 453 | "metadata": {}, 454 | "output_type": "execute_result" 455 | } 456 | ], 457 | "source": [ 458 | "conversation.predict(input=\"How is it different from a Llama?\")" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 20, 464 | "metadata": {}, 465 | "outputs": [ 466 | { 467 | "name": "stderr", 468 | "output_type": "stream", 469 | "text": [ 470 | "Input length of input_ids is 276, but `max_length` is set to 256. This can lead to unexpected behavior. You should consider increasing `max_new_tokens`.\n" 471 | ] 472 | }, 473 | { 474 | "name": "stdout", 475 | "output_type": "stream", 476 | "text": [ 477 | "\n", 478 | "\n", 479 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 480 | "Prompt after formatting:\n", 481 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 482 | " \n", 483 | "Current conversation:\n", 484 | "Human: Hi there! I am Isuru\n", 485 | "AI: Hey there! It's nice to meet you too. What can I help you with?\n", 486 | "Human: What is your name?\n", 487 | "AI: My name is Alpaca. How did you come up with that name?\n", 488 | "Human: Can you tell me what an Alpaca is?\n", 489 | "AI: Sure. An alpaca is a species of South American camelid mammal. They are typically found in the Andes mountains and live in herds led by an alpha female leader.\n", 490 | "Human: How is it different from a Llama?\n", 491 | "AI: Alpacas and llamas belong to the same family but they have some differences as well. Alpacas tend to be smaller than llamas and they lack the long ear frills that llamas have. Additionally, their fleece is finer\n", 492 | "Human: Can you give me some good names for a pet llama?\n", 493 | "AI:\u001b[0m\n", 494 | "\n", 495 | "\u001b[1m> Finished chain.\u001b[0m\n" 496 | ] 497 | }, 498 | { 499 | "data": { 500 | "text/plain": [ 501 | "' '" 502 | ] 503 | }, 504 | "execution_count": 20, 505 | "metadata": {}, 506 | "output_type": "execute_result" 507 | } 508 | ], 509 | "source": [ 510 | "conversation.predict(input=\"Can you give me some good names for a pet llama?\")" 511 | ] 512 | }, 513 | { 514 | "cell_type": "code", 515 | "execution_count": 21, 516 | "metadata": {}, 517 | "outputs": [ 518 | { 519 | "name": "stderr", 520 | "output_type": "stream", 521 | "text": [ 522 | "Input length of input_ids is 257, but `max_length` is set to 256. This can lead to unexpected behavior. You should consider increasing `max_new_tokens`.\n" 523 | ] 524 | }, 525 | { 526 | "name": "stdout", 527 | "output_type": "stream", 528 | "text": [ 529 | "\n", 530 | "\n", 531 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 532 | "Prompt after formatting:\n", 533 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 534 | " \n", 535 | "Current conversation:\n", 536 | "Human: What is your name?\n", 537 | "AI: My name is Alpaca. How did you come up with that name?\n", 538 | "Human: Can you tell me what an Alpaca is?\n", 539 | "AI: Sure. An alpaca is a species of South American camelid mammal. They are typically found in the Andes mountains and live in herds led by an alpha female leader.\n", 540 | "Human: How is it different from a Llama?\n", 541 | "AI: Alpacas and llamas belong to the same family but they have some differences as well. Alpacas tend to be smaller than llamas and they lack the long ear frills that llamas have. Additionally, their fleece is finer\n", 542 | "Human: Can you give me some good names for a pet llama?\n", 543 | "AI: \n", 544 | "Human: Is your name LLaMA?\n", 545 | "AI:\u001b[0m\n", 546 | "\n", 547 | "\u001b[1m> Finished chain.\u001b[0m\n" 548 | ] 549 | }, 550 | { 551 | "data": { 552 | "text/plain": [ 553 | "' No'" 554 | ] 555 | }, 556 | "execution_count": 21, 557 | "metadata": {}, 558 | "output_type": "execute_result" 559 | } 560 | ], 561 | "source": [ 562 | "conversation.predict(input=\"Is your name LLaMA?\")" 563 | ] 564 | }, 565 | { 566 | "cell_type": "code", 567 | "execution_count": 22, 568 | "metadata": {}, 569 | "outputs": [ 570 | { 571 | "name": "stdout", 572 | "output_type": "stream", 573 | "text": [ 574 | "\n", 575 | "\n", 576 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 577 | "Prompt after formatting:\n", 578 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI called Alpaca. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. \n", 579 | " \n", 580 | "Current conversation:\n", 581 | "Human: Can you tell me what an Alpaca is?\n", 582 | "AI: Sure. An alpaca is a species of South American camelid mammal. They are typically found in the Andes mountains and live in herds led by an alpha female leader.\n", 583 | "Human: How is it different from a Llama?\n", 584 | "AI: Alpacas and llamas belong to the same family but they have some differences as well. Alpacas tend to be smaller than llamas and they lack the long ear frills that llamas have. Additionally, their fleece is finer\n", 585 | "Human: Can you give me some good names for a pet llama?\n", 586 | "AI: \n", 587 | "Human: Is your name LLaMA?\n", 588 | "AI: No\n", 589 | "Human: What food should I feed my new llama?\n", 590 | "AI:\u001b[0m\n", 591 | "\n", 592 | "\u001b[1m> Finished chain.\u001b[0m\n" 593 | ] 594 | }, 595 | { 596 | "data": { 597 | "text/plain": [ 598 | "' Your new llama should eat grass,'" 599 | ] 600 | }, 601 | "execution_count": 22, 602 | "metadata": {}, 603 | "output_type": "execute_result" 604 | } 605 | ], 606 | "source": [ 607 | "conversation.predict(input=\"What food should I feed my new llama?\")" 608 | ] 609 | }, 610 | { 611 | "cell_type": "code", 612 | "execution_count": null, 613 | "metadata": {}, 614 | "outputs": [], 615 | "source": [] 616 | } 617 | ], 618 | "metadata": { 619 | "kernelspec": { 620 | "display_name": "torch113", 621 | "language": "python", 622 | "name": "python3" 623 | }, 624 | "language_info": { 625 | "codemirror_mode": { 626 | "name": "ipython", 627 | "version": 3 628 | }, 629 | "file_extension": ".py", 630 | "mimetype": "text/x-python", 631 | "name": "python", 632 | "nbconvert_exporter": "python", 633 | "pygments_lexer": "ipython3", 634 | "version": "3.8.16" 635 | } 636 | }, 637 | "nbformat": 4, 638 | "nbformat_minor": 4 639 | } 640 | -------------------------------------------------------------------------------- /Chat-with-Flang20B-LangChain-HuggingFace.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "import yaml, openai\n", 11 | "from langchain import OpenAI\n", 12 | "from pydantic import BaseModel\n", 13 | "from typing import List, Dict, Any\n", 14 | "from langchain.llms import HuggingFaceHub\n", 15 | "from langchain.chains import ConversationChain\n", 16 | "from langchain.prompts.prompt import PromptTemplate\n", 17 | "from langchain.chains.conversation.memory import ConversationBufferMemory" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 2, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "with open('cadentials.yaml') as f:\n", 27 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 28 | "\n", 29 | "os.environ['OPENAI_API_KEY'] = credentials['OPENAI_API_KEY']\n", 30 | "os.environ['HUGGINGFACEHUB_API_TOKEN'] = credentials['HUGGINGFACEHUB_API_TOKEN']\n", 31 | "openai.api_key = credentials['OPENAI_API_KEY']" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 3, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stderr", 41 | "output_type": "stream", 42 | "text": [ 43 | "C:\\Users\\Legion\\AppData\\Roaming\\Python\\Python38\\site-packages\\tqdm\\auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", 44 | " from .autonotebook import tqdm as notebook_tqdm\n" 45 | ] 46 | } 47 | ], 48 | "source": [ 49 | "flan_ul2 = HuggingFaceHub(\n", 50 | " repo_id=\"google/flan-ul2\", \n", 51 | " model_kwargs={\n", 52 | " \"temperature\":0.1,\n", 53 | " \"max_new_tokens\":256\n", 54 | " }\n", 55 | " )\n", 56 | "\n", 57 | "flan_t5 = HuggingFaceHub(\n", 58 | " repo_id=\"google/flan-t5-xl\",\n", 59 | " model_kwargs={\"temperature\":0 }\n", 60 | " )\n", 61 | "\n", 62 | "memory = ConversationBufferMemory()\n", 63 | "\n", 64 | "conversation = ConversationChain(\n", 65 | " llm=flan_ul2, \n", 66 | " verbose=True, \n", 67 | " memory=memory\n", 68 | " )" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 4, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "\n", 81 | "\n", 82 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 83 | "Prompt after formatting:\n", 84 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", 85 | "\n", 86 | "Current conversation:\n", 87 | "\n", 88 | "Human: Hi there! I am Isuru\n", 89 | "AI:\u001b[0m\n", 90 | "\n", 91 | "\u001b[1m> Finished chain.\u001b[0m\n" 92 | ] 93 | }, 94 | { 95 | "data": { 96 | "text/plain": [ 97 | "'Hi, I am Isuru. What can I help you with?'" 98 | ] 99 | }, 100 | "execution_count": 4, 101 | "metadata": {}, 102 | "output_type": "execute_result" 103 | } 104 | ], 105 | "source": [ 106 | "conversation.predict(input=\"Hi there! I am Isuru\")" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 5, 112 | "metadata": {}, 113 | "outputs": [ 114 | { 115 | "name": "stdout", 116 | "output_type": "stream", 117 | "text": [ 118 | "\n", 119 | "\n", 120 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 121 | "Prompt after formatting:\n", 122 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", 123 | "\n", 124 | "Current conversation:\n", 125 | "Human: Hi there! I am Isuru\n", 126 | "AI: Hi, I am Isuru. What can I help you with?\n", 127 | "Human: I am very lazy now to go to the gym. I am thinking to skip it today. Help me to decide.\n", 128 | "AI:\u001b[0m\n", 129 | "\n", 130 | "\u001b[1m> Finished chain.\u001b[0m\n" 131 | ] 132 | }, 133 | { 134 | "data": { 135 | "text/plain": [ 136 | "'I can help you with that. I can check your calendar and see if you have any appointments today.'" 137 | ] 138 | }, 139 | "execution_count": 5, 140 | "metadata": {}, 141 | "output_type": "execute_result" 142 | } 143 | ], 144 | "source": [ 145 | "conversation.predict(input=\"I am very lazy now to go to the gym. I am thinking to skip it today. Help me to decide.\")" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 6, 151 | "metadata": {}, 152 | "outputs": [ 153 | { 154 | "name": "stdout", 155 | "output_type": "stream", 156 | "text": [ 157 | "\n", 158 | "\n", 159 | "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n", 160 | "Prompt after formatting:\n", 161 | "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n", 162 | "\n", 163 | "Current conversation:\n", 164 | "Human: Hi there! I am Isuru\n", 165 | "AI: Hi, I am Isuru. What can I help you with?\n", 166 | "Human: I am very lazy now to go to the gym. I am thinking to skip it today. Help me to decide.\n", 167 | "AI: I can help you with that. I can check your calendar and see if you have any appointments today.\n", 168 | "Human: Thanks for your help. I will go to the gym today.\n", 169 | "AI:\u001b[0m\n", 170 | "\n", 171 | "\u001b[1m> Finished chain.\u001b[0m\n" 172 | ] 173 | }, 174 | { 175 | "data": { 176 | "text/plain": [ 177 | "'I am glad to help.'" 178 | ] 179 | }, 180 | "execution_count": 6, 181 | "metadata": {}, 182 | "output_type": "execute_result" 183 | } 184 | ], 185 | "source": [ 186 | "conversation.predict(input=\"Thanks for your help. I will go to the gym today.\")" 187 | ] 188 | } 189 | ], 190 | "metadata": { 191 | "kernelspec": { 192 | "display_name": "torch113", 193 | "language": "python", 194 | "name": "python3" 195 | }, 196 | "language_info": { 197 | "codemirror_mode": { 198 | "name": "ipython", 199 | "version": 3 200 | }, 201 | "file_extension": ".py", 202 | "mimetype": "text/x-python", 203 | "name": "python", 204 | "nbconvert_exporter": "python", 205 | "pygments_lexer": "ipython3", 206 | "version": "3.8.16" 207 | }, 208 | "orig_nbformat": 4 209 | }, 210 | "nbformat": 4, 211 | "nbformat_minor": 2 212 | } 213 | -------------------------------------------------------------------------------- /ChatGPT🤝LangChain🔥.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 6, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "import yaml, openai\n", 11 | "from langchain import PromptTemplate\n", 12 | "from langchain.chains import LLMChain\n", 13 | "from langchain.llms import OpenAI, OpenAIChat" 14 | ] 15 | }, 16 | { 17 | "attachments": {}, 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# ChatGPT API Basics" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 7, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "with open('cadentials.yaml') as f:\n", 31 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 32 | "\n", 33 | "os.environ['OPENAI_API_KEY'] = credentials['OPENAI_API_KEY']\n", 34 | "os.environ['HUGGINGFACEHUB_API_TOKEN'] = credentials['HUGGINGFACEHUB_API_TOKEN']\n", 35 | "openai.api_key = credentials['OPENAI_API_KEY']" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 8, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/plain": [ 46 | " JSON: {\n", 47 | " \"choices\": [\n", 48 | " {\n", 49 | " \"finish_reason\": \"stop\",\n", 50 | " \"index\": 0,\n", 51 | " \"message\": {\n", 52 | " \"content\": \"I am an AI-powered language model assistant designed to help you with various tasks like answering questions, providing information, assisting with tasks, and more. How may I assist you today?\",\n", 53 | " \"role\": \"assistant\"\n", 54 | " }\n", 55 | " }\n", 56 | " ],\n", 57 | " \"created\": 1680775054,\n", 58 | " \"id\": \"chatcmpl-72Gf0fYWY3kqLHrSHUEKWfJSpBj7Q\",\n", 59 | " \"model\": \"gpt-3.5-turbo-0301\",\n", 60 | " \"object\": \"chat.completion\",\n", 61 | " \"usage\": {\n", 62 | " \"completion_tokens\": 36,\n", 63 | " \"prompt_tokens\": 27,\n", 64 | " \"total_tokens\": 63\n", 65 | " }\n", 66 | "}" 67 | ] 68 | }, 69 | "execution_count": 8, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "response = openai.ChatCompletion.create(\n", 76 | " model=\"gpt-3.5-turbo\",\n", 77 | " messages=[\n", 78 | " {\"role\": \"assistant\", \"content\": \"You are a helpful assistant.\"},\n", 79 | " {\"role\": \"user\", \"content\": \"Hello what kind of assistant are you?\"},\n", 80 | " ]\n", 81 | " )\n", 82 | "response" 83 | ] 84 | }, 85 | { 86 | "attachments": {}, 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "### Chat Mark-up Language (CML) Token System\n", 91 | "\n", 92 | " <|im_start|>system\n", 93 | " You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.\n", 94 | " Knowledge cutoff: 2021-09-01\n", 95 | " Current date: 2023-03-01<|im_end|>\n", 96 | " <|im_start|>user\n", 97 | " How are you<|im_end|>\n", 98 | " <|im_start|>assistant\n", 99 | " I am doing well!<|im_end|>\n", 100 | " <|im_start|>user\n", 101 | " How are you now?<|im_end|>" 102 | ] 103 | }, 104 | { 105 | "attachments": {}, 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "### system tells what kind of role the LLM should play. Key thing to note is that Token system which discribedmay changes based on the role of the LLM. " 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 9, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "messages = [\n", 119 | " {\"role\": \"assistant\", \"content\": \"You are a helpful assistant.\"},\n", 120 | " {\"role\": \"user\", \"content\": \"Hello what kind of assistant are you?\"},\n", 121 | " ]" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 10, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stdout", 131 | "output_type": "stream", 132 | "text": [ 133 | "ChatGPT: Hello Isuru! I am an AI language model created by OpenAI, so I don't have a name like a human. You can call me OpenAI if you like. How may I assist you today? \n", 134 | " 88 tokens used\n", 135 | "ChatGPT: As an AI language model, I don't have the capacity to compare and judge myself against other models or products. While I can certainly help you with language-related tasks, my capabilities and limitations are determined by my training dataset, programming, and other technical factors rather than marketing claims or comparisons. Nevertheless, I'd be happy to answer any questions you have or help you in any way I can. \n", 136 | " 202 tokens used\n", 137 | "ChatGPT: Yes, I can generate word embeddings using a pre-trained language model such as GPT-2 or Word2Vec. Word embeddings are numerical representations of words that are generated by analyzing large amounts of text data. They enable computers to understand the semantic relationships between words, such as synonyms, antonyms, and context. These embeddings can be used in various natural language processing (NLP) applications, such as language translation, sentiment analysis, and speech recognition. If you have more questions regarding word embeddings or NLP, feel free to ask. \n", 138 | " 326 tokens used\n", 139 | "616 tokens used in total in this conversation\n" 140 | ] 141 | } 142 | ], 143 | "source": [ 144 | "conversation_total_tokens = 0\n", 145 | "\n", 146 | "while True:\n", 147 | " message = input(\"Human: \")\n", 148 | " if message=='exit':\n", 149 | " print(f\"{conversation_total_tokens} tokens used in total in this conversation\")\n", 150 | " break\n", 151 | " if message:\n", 152 | " messages.append(\n", 153 | " {\n", 154 | " \"role\": \"user\", \n", 155 | " \"content\": message\n", 156 | " },\n", 157 | " )\n", 158 | " response = openai.ChatCompletion.create(\n", 159 | " model=\"gpt-3.5-turbo\", \n", 160 | " messages=messages\n", 161 | " )\n", 162 | " \n", 163 | " reply = response.choices[0].message.content\n", 164 | " total_tokens = response.usage['total_tokens']\n", 165 | " conversation_total_tokens += total_tokens\n", 166 | " print(f\"ChatGPT: {reply} \\n {total_tokens} tokens used\")\n", 167 | " messages.append({\"role\": \"assistant\", \"content\": reply})" 168 | ] 169 | }, 170 | { 171 | "attachments": {}, 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "#### I'm Impressed about GPTx" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [] 184 | }, 185 | { 186 | "attachments": {}, 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "# ChatGPT with LangChain" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 12, 196 | "metadata": {}, 197 | "outputs": [], 198 | "source": [ 199 | "prefix_messages = [\n", 200 | " {\n", 201 | " \"role\": \"system\", \n", 202 | " \"content\": \"You are a helpful history professor named Kate.\"\n", 203 | " }\n", 204 | " ]\n", 205 | "\n", 206 | "llm = OpenAIChat(\n", 207 | " model_name='gpt-3.5-turbo', \n", 208 | " temperature=0, \n", 209 | " prefix_messages=prefix_messages,\n", 210 | " max_tokens = 256\n", 211 | " )" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 13, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "template = \"\"\"Take the following question: {user_input}\n", 221 | "\n", 222 | "Answer it in an informative and intersting but conscise way for someone who is new to this topic.\"\"\"\n", 223 | "\n", 224 | "prompt = PromptTemplate(\n", 225 | " template=template, \n", 226 | " input_variables=[\"user_input\"]\n", 227 | " )\n" 228 | ] 229 | }, 230 | { 231 | "attachments": {}, 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "#### example 01" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 16, 241 | "metadata": {}, 242 | "outputs": [ 243 | { 244 | "data": { 245 | "text/plain": [ 246 | "'Large Language Models are computer programs that use artificial intelligence to generate human-like language. They work by analyzing vast amounts of text data, such as books, articles, and websites, to learn the patterns and structures of language. This allows them to generate new text that is similar in style and tone to the original data.\\n\\nOne of the most well-known examples of a Large Language Model is GPT-3, which has been trained on a massive dataset of over 45 terabytes of text. This model can generate a wide range of text, from news articles to poetry to computer code.\\n\\nLarge Language Models are used in a variety of applications, such as chatbots, language translation, and content creation. They have the potential to revolutionize the way we interact with technology and communicate with each other. However, there are also concerns about the ethical implications of these models, such as the potential for bias and the impact on human creativity.'" 247 | ] 248 | }, 249 | "execution_count": 16, 250 | "metadata": {}, 251 | "output_type": "execute_result" 252 | } 253 | ], 254 | "source": [ 255 | "llm_chain = LLMChain(prompt=prompt, llm=llm)\n", 256 | "\n", 257 | "user_input = \"Describe Large Language Models and how they work.\"\n", 258 | "\n", 259 | "llm_chain.run(user_input)" 260 | ] 261 | }, 262 | { 263 | "attachments": {}, 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "#### example 02" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 17, 273 | "metadata": {}, 274 | "outputs": [ 275 | { 276 | "data": { 277 | "text/plain": [ 278 | "\"GPT-3 is a language model that uses artificial intelligence to generate human-like text. It works by analyzing vast amounts of text data and learning patterns and relationships between words and phrases. This allows it to generate coherent and contextually appropriate responses to prompts or questions. Essentially, it's like a very advanced version of predictive text on your phone, but on a much larger scale. It has the potential to revolutionize the way we interact with technology and communicate with each other.\"" 279 | ] 280 | }, 281 | "execution_count": 17, 282 | "metadata": {}, 283 | "output_type": "execute_result" 284 | } 285 | ], 286 | "source": [ 287 | "llm_chain = LLMChain(prompt=prompt, llm=llm)\n", 288 | "\n", 289 | "user_input = \"Describe the GPT-3 model and how it works.\"\n", 290 | "\n", 291 | "llm_chain.run(user_input)" 292 | ] 293 | } 294 | ], 295 | "metadata": { 296 | "kernelspec": { 297 | "display_name": "torch113", 298 | "language": "python", 299 | "name": "python3" 300 | }, 301 | "language_info": { 302 | "codemirror_mode": { 303 | "name": "ipython", 304 | "version": 3 305 | }, 306 | "file_extension": ".py", 307 | "mimetype": "text/x-python", 308 | "name": "python", 309 | "nbconvert_exporter": "python", 310 | "pygments_lexer": "ipython3", 311 | "version": "3.8.16" 312 | }, 313 | "orig_nbformat": 4 314 | }, 315 | "nbformat": 4, 316 | "nbformat_minor": 2 317 | } 318 | -------------------------------------------------------------------------------- /HuggingFaceHub🤝LangChain-Work-Local.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "import yaml\n", 11 | "import torch\n", 12 | "from langchain.llms import HuggingFacePipeline\n", 13 | "from langchain import PromptTemplate, HuggingFaceHub, LLMChain\n", 14 | "from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, AutoModelForSeq2SeqLM" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "### 2 Ways to do this.\n", 23 | " - Use HuggingFaceHub (But it doesn't support all the models)\n", 24 | " - Local Pipeline" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "with open('cadentials.yaml') as f:\n", 34 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 35 | "\n", 36 | "os.environ['HUGGINGFACEHUB_API_TOKEN'] = credentials['HUGGINGFACEHUB_API_TOKEN']" 37 | ] 38 | }, 39 | { 40 | "attachments": {}, 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "### 1. HuggingFaceHub" 45 | ] 46 | }, 47 | { 48 | "attachments": {}, 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "#### 1.1 Flang-T5" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "template = \"\"\"Question: {question}\n", 62 | "\n", 63 | "Answer: Let's think step by step.\"\"\"\n", 64 | "\n", 65 | "prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n", 66 | "\n", 67 | "llm_chain = LLMChain(\n", 68 | " prompt=prompt, \n", 69 | " llm=HuggingFaceHub(\n", 70 | " repo_id=\"google/flan-t5-xl\", \n", 71 | " model_kwargs={\n", 72 | " \"temperature\":0, \n", 73 | " \"max_length\":64\n", 74 | " }\n", 75 | " )\n", 76 | " )" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "question = \"What is the capital of France?\"\n", 86 | "\n", 87 | "print(llm_chain.run(question))" 88 | ] 89 | }, 90 | { 91 | "attachments": {}, 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "#### 1.2 BlenderBot" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "template = \"\"\"Question: {question}\n", 105 | "\n", 106 | "Answer: Let's think step by step.\"\"\"\n", 107 | "\n", 108 | "prompt = PromptTemplate(template=template, input_variables=[\"question\"])\n", 109 | "\n", 110 | "try:\n", 111 | " blenderbot_chain = LLMChain(\n", 112 | " prompt=prompt, \n", 113 | " llm=HuggingFaceHub(\n", 114 | " repo_id=\"facebook/blenderbot-1B-distill\", \n", 115 | " model_kwargs={\n", 116 | " \"temperature\":0, \n", 117 | " \"max_length\":64\n", 118 | " }\n", 119 | " ))\n", 120 | "\n", 121 | "except:\n", 122 | " print(\"Blenderbot is not available on HuggingFaceHub\")" 123 | ] 124 | }, 125 | { 126 | "attachments": {}, 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "#### SEEEEEEEEEEEEEEEE !!!!!!!" 131 | ] 132 | }, 133 | { 134 | "attachments": {}, 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "### 2. Local Pipeline" 139 | ] 140 | }, 141 | { 142 | "attachments": {}, 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "#### 2.1 Flang-T5 text2text generation (Encoder-Decoder)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "model_id = 'google/flan-t5-large'# go for a smaller model if you dont have the VRAM\n", 156 | "tokenizer = AutoTokenizer.from_pretrained(model_id)\n", 157 | "model = AutoModelForSeq2SeqLM.from_pretrained(model_id, load_in_8bit=True)\n", 158 | "\n", 159 | "pipe = pipeline(\n", 160 | " \"text2text-generation\",\n", 161 | " model=model, \n", 162 | " tokenizer=tokenizer, \n", 163 | " max_length=100\n", 164 | " )\n", 165 | "\n", 166 | "local_llm = HuggingFacePipeline(pipeline=pipe)" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [ 175 | "print(local_llm('What is the capital of France? '))" 176 | ] 177 | }, 178 | { 179 | "attachments": {}, 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "#### 2.2 GPT2-medium text generation (Decoder Only)" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "name": "stderr", 193 | "output_type": "stream", 194 | "text": [ 195 | "Downloading (…)\"pytorch_model.bin\";: 1%| | 10.5M/1.52G [00:14<01:47, 14.0MB/s]" 196 | ] 197 | } 198 | ], 199 | "source": [ 200 | "model_id = \"gpt2-medium\"\n", 201 | "tokenizer = AutoTokenizer.from_pretrained(model_id)\n", 202 | "model = AutoModelForCausalLM.from_pretrained(model_id)\n", 203 | "\n", 204 | "pipe = pipeline(\n", 205 | " \"text-generation\", \n", 206 | " model=model, \n", 207 | " tokenizer=tokenizer, \n", 208 | " max_length=100\n", 209 | ")\n", 210 | "\n", 211 | "local_llm = HuggingFacePipeline(pipeline=pipe)" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "print(local_llm('What is the capital of France? '))" 221 | ] 222 | } 223 | ], 224 | "metadata": { 225 | "kernelspec": { 226 | "display_name": "torch113", 227 | "language": "python", 228 | "name": "python3" 229 | }, 230 | "language_info": { 231 | "codemirror_mode": { 232 | "name": "ipython", 233 | "version": 3 234 | }, 235 | "file_extension": ".py", 236 | "mimetype": "text/x-python", 237 | "name": "python", 238 | "nbconvert_exporter": "python", 239 | "pygments_lexer": "ipython3", 240 | "version": "3.8.16" 241 | }, 242 | "orig_nbformat": 4 243 | }, 244 | "nbformat": 4, 245 | "nbformat_minor": 2 246 | } 247 | -------------------------------------------------------------------------------- /LLM-Prompting-Basics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 12, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "!pip -q install openai langchain huggingface_hub" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 22, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import os\n", 19 | "import yaml\n", 20 | "from langchain.llms import OpenAI\n", 21 | "from langchain import PromptTemplate\n", 22 | "from langchain.chains import LLMChain" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 15, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "with open('cadentials.yaml') as f:\n", 32 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 33 | "\n", 34 | "os.environ['OPENAI_API_KEY'] = credentials['OPENAI_API_KEY']\n", 35 | "os.environ['HUGGINGFACEHUB_API_TOKEN'] = credentials['HUGGINGFACEHUB_API_TOKEN']" 36 | ] 37 | }, 38 | { 39 | "attachments": {}, 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "## GPT3 Experiment: LLM-Prompting-Basics" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 16, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "llm = OpenAI(\n", 53 | " model_name='text-davinci-003', \n", 54 | " temperature=0.9, \n", 55 | " max_tokens = 256\n", 56 | " )" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 20, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "name": "stdout", 66 | "output_type": "stream", 67 | "text": [ 68 | "\n", 69 | "\n", 70 | "To get to the other side.\n" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "text = \"Why did the duck cross the road?\"\n", 76 | "gen = llm(text)\n", 77 | "print(gen)" 78 | ] 79 | }, 80 | { 81 | "attachments": {}, 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "## Let's Make things more useful ; Prompt Templates" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 24, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "\n", 95 | "restaurant_template = \"\"\"\n", 96 | " I want you to act as a naming consultant for new restaurants.\n", 97 | "\n", 98 | " Return a list of restaurant names. Each name should be short, catchy and easy to remember. It shoud relate to the type of restaurant you are naming.\n", 99 | "\n", 100 | " What are some good names for a restaurant that is {restaurant_desription}?\n", 101 | " \"\"\"\n", 102 | "\n", 103 | "prompt = PromptTemplate(\n", 104 | " input_variables=[\"restaurant_desription\"],\n", 105 | " template=restaurant_template,\n", 106 | " )\n", 107 | " \n", 108 | "chain = LLMChain(llm=llm, prompt=prompt)" 109 | ] 110 | }, 111 | { 112 | "attachments": {}, 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "#### see. now you can apply this prompt for variety of restaurant desriptions as mentioned in below cell" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 27, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | "#### a Greek place that serves fresh lamb souvlakis and other Greek food ####\n", 129 | "\n", 130 | "1. The Souvlaki Spot\n", 131 | "2. Lamb Lover's Paradise\n", 132 | "3. Zeus' Kitchen\n", 133 | "4. Athena's Delight\n", 134 | "5. The Greek Grill\n", 135 | "6. Grecian Treats\n", 136 | "7. Souvlaki Shack\n", 137 | "8. The Mainland\n", 138 | "9. Aegean Platter\n", 139 | "10. The Appetizer Palace\n", 140 | "#### a burger place that is themed with baseball memorabilia ####\n", 141 | "\n", 142 | " - The Home Plate\n", 143 | " - Slugger Burger\n", 144 | " - MVP Grill\n", 145 | " - The Bullpen Burger\n", 146 | " - Batter Up Burgers\n", 147 | " - Grand Slam Grill\n", 148 | " - Fastball Cafe\n", 149 | " - Grandstand Grill\n", 150 | " - Strike Zone Grill\n", 151 | " - Big League Burgers\n", 152 | " - Diamond Dog Cafe\n", 153 | " - All Star Eatery\n", 154 | "#### a cafe that has live hard rock music and memorabilia ####\n", 155 | "\n", 156 | "1. Rockin' Cafe \n", 157 | "2. Hard Rock Grill \n", 158 | "3. Full Volume Cafe \n", 159 | "4. Electric Cafe \n", 160 | "5. Amplified Eatery \n", 161 | "6. Live Music Bistro \n", 162 | "7. Rock Out Diner \n", 163 | "8. Rock Cafe \n", 164 | "9. Rockstar Eatery \n", 165 | "10. Rock & Roll Cafe\n", 166 | "#### a restaurant that serves only vegetarian food ####\n", 167 | "\n", 168 | "1. Green Garden\n", 169 | "2. Veggie Haven\n", 170 | "3. Garden Fresh\n", 171 | "4. The Veg Spot\n", 172 | "5. Sprout Spot\n", 173 | "6. Earthy Eats\n", 174 | "7. Vege Delight\n", 175 | "8. The Garden Plate\n", 176 | "9. Plant Plate\n", 177 | "10. Veg Out\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "descriptions = [\n", 183 | " \"a Greek place that serves fresh lamb souvlakis and other Greek food \",\n", 184 | " \"a burger place that is themed with baseball memorabilia\",\n", 185 | " \"a cafe that has live hard rock music and memorabilia\",\n", 186 | " \"a restaurant that serves only vegetarian food\",\n", 187 | " ]\n", 188 | "\n", 189 | "## to see what the prompt will be like\n", 190 | "for description in descriptions:\n", 191 | " result = chain.run(description)\n", 192 | " print(\"#### {} ####\".format(description))\n", 193 | " print(result)\n", 194 | " " 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [] 203 | } 204 | ], 205 | "metadata": { 206 | "kernelspec": { 207 | "display_name": "torch113", 208 | "language": "python", 209 | "name": "python3" 210 | }, 211 | "language_info": { 212 | "codemirror_mode": { 213 | "name": "ipython", 214 | "version": 3 215 | }, 216 | "file_extension": ".py", 217 | "mimetype": "text/x-python", 218 | "name": "python", 219 | "nbconvert_exporter": "python", 220 | "pygments_lexer": "ipython3", 221 | "version": "3.8.16" 222 | }, 223 | "orig_nbformat": 4 224 | }, 225 | "nbformat": 4, 226 | "nbformat_minor": 2 227 | } 228 | -------------------------------------------------------------------------------- /PAL-Chain-of-Thought-Modeling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": { 5 | "image.png": { 6 | "image/png": "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" 7 | } 8 | }, 9 | "cell_type": "markdown", 10 | "metadata": {}, 11 | "source": [ 12 | "![image.png](attachment:image.png)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": null, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "import os\n", 22 | "import yaml, openai\n", 23 | "from langchain import OpenAI\n", 24 | "from langchain import PromptTemplate\n", 25 | "from langchain.chains import PALChain\n", 26 | "from langchain.chains.llm import LLMChain" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "with open('cadentials.yaml') as f:\n", 36 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 37 | "\n", 38 | "os.environ['OPENAI_API_KEY'] = credentials['OPENAI_API_KEY']\n", 39 | "openai.api_key = credentials['OPENAI_API_KEY']" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "llm = OpenAI(\n", 49 | " model_name='code-davinci-002', \n", 50 | " temperature=0, \n", 51 | " max_tokens=512\n", 52 | " )\n", 53 | "\n", 54 | "pal_chain = PALChain.from_math_prompt(llm, verbose=True)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "question = \"The cafeteria had 23 apples. \\\n", 64 | "If they used 20 for lunch and bought 6 more,\\\n", 65 | "how many apples do they have?\"\n", 66 | "\n", 67 | "pal_chain.run(question)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [] 76 | } 77 | ], 78 | "metadata": { 79 | "kernelspec": { 80 | "display_name": "torch113", 81 | "language": "python", 82 | "name": "python3" 83 | }, 84 | "language_info": { 85 | "codemirror_mode": { 86 | "name": "ipython", 87 | "version": 3 88 | }, 89 | "file_extension": ".py", 90 | "mimetype": "text/x-python", 91 | "name": "python", 92 | "nbconvert_exporter": "python", 93 | "pygments_lexer": "ipython3", 94 | "version": "3.8.16" 95 | }, 96 | "orig_nbformat": 4 97 | }, 98 | "nbformat": 4, 99 | "nbformat_minor": 2 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # build-generative-ai-apps-with-langchain 2 | 3 | "Build Generative AI Apps with LangChain" is a repository that contains a comprehensive framework for building generative AI applications using LangChain, an innovative language modeling platform. This repository includes all the necessary code and documentation to help developers quickly build and deploy generative AI applications 4 | 5 | ### Installation 6 | pip -q install openai langchain huggingface_hub 7 | pip install --upgrade openai 8 | 9 | create cadentials.yaml which has below template 10 | 11 | OPENAI_API_KEY: <> 12 | HUGGINGFACEHUB_API_TOKEN: <> 13 | 14 | ### LangChain Notebooks 15 | - Basic LLM Prompting with Langchain [Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/LLM-Prompting-Basics.ipynb) 16 | 17 | - Build First Sequential Chain with Langchain [Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/The-First-Sequential-Chain.ipynb) 18 | 19 | - ChatGPT meets LangChain , The Brothers of Destruction 🔥[Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/ChatGPT🤝LangChain🔥.ipynb) 20 | 21 | - Maintain Conversations with Memory 🔥[Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/Conversations-with-Memory.ipynb) 22 | 23 | - HuggingFaceHub IN🔥 OpenAI OUT[Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/Chat-with-Flang20B-LangChain-HuggingFace.ipynb) 24 | 25 | - HuggingFaceHub🤝LangChain Work Local[Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/HuggingFaceHub🤝LangChain-Work-Local.ipynb) 26 | 27 | - PAL : The Chain of Thought Modeling[Notebook](https://github.com/1zuu/build-generative-ai-apps-with-langchain/blob/main/PAL-Chain-of-Thought-Modeling.ipynb) -------------------------------------------------------------------------------- /The-First-Sequential-Chain.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "import yaml\n", 11 | "from langchain.llms import OpenAI\n", 12 | "from langchain import PromptTemplate\n", 13 | "from langchain.chains import LLMChain" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 2, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "with open('cadentials.yaml') as f:\n", 23 | " credentials = yaml.load(f, Loader=yaml.FullLoader)\n", 24 | "\n", 25 | "os.environ['OPENAI_API_KEY'] = credentials['OPENAI_API_KEY']\n", 26 | "os.environ['HUGGINGFACEHUB_API_TOKEN'] = credentials['HUGGINGFACEHUB_API_TOKEN']" 27 | ] 28 | }, 29 | { 30 | "attachments": {}, 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "## Phase 01 - Fact Extraction LLMChain " 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 3, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "llm = OpenAI(\n", 44 | " model_name='text-davinci-003', \n", 45 | " temperature=0, \n", 46 | " max_tokens = 256\n", 47 | " )" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 4, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "prompt_01 = \"Extract the key facts out of this text. Don't include opinions. Give each fact a number and keep them short sentences. :\\n\\n {text_input}\"\n", 57 | "\n", 58 | "fact_extraction_prompt = PromptTemplate(\n", 59 | " input_variables=[\"text_input\"],\n", 60 | " template=prompt_01\n", 61 | " )\n", 62 | "\n", 63 | "fact_extraction_chain = LLMChain(\n", 64 | " llm=llm,\n", 65 | " prompt=fact_extraction_prompt\n", 66 | " )" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 5, 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "\n", 79 | "1. Coinbase released its Q4 2022 earnings on Tuesday.\n", 80 | "2. Coinbase generated $605 million in total revenue in Q4 2022.\n", 81 | "3. Coinbase lost $557 million in the three-month period on a GAAP basis.\n", 82 | "4. Wall Street expected Coinbase to report $581.2 million in revenue.\n", 83 | "5. Coinbase's stock had risen 86% year-to-date before its Q4 earnings were released.\n", 84 | "6. Consumer trading volumes fell from $26 billion in Q3 2022 to $20 billion in Q4 2022.\n", 85 | "7. Institutional volumes across the same timeframe fell from $133 billion to $125 billion.\n", 86 | "8. The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022.\n", 87 | "9. Coinbase's total trading volumes and transaction revenues fell 50% and 66% year-over-year, respectively.\n", 88 | "10. Trading revenue at Coinbase fell from $365.9 million in Q3 2022 to $322.1 million in Q4 2022.\n", 89 | "11. Coinbase's \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 2022.\n", 90 | "12. Monthly active developers in crypto have more than doubled since\n" 91 | ] 92 | } 93 | ], 94 | "source": [ 95 | "article = '''Coinbase, the second-largest crypto exchange by trading volume, released its Q4 2022 earnings on Tuesday, giving shareholders and market players alike an updated look into its financials. In response to the report, the company's shares are down modestly in early after-hours trading.In the fourth quarter of 2022, Coinbase generated $605 million in total revenue, down sharply from $2.49 billion in the year-ago quarter. Coinbase's top line was not enough to cover its expenses: The company lost $557 million in the three-month period on a GAAP basis (net income) worth -$2.46 per share, and an adjusted EBITDA deficit of $124 million.Wall Street expected Coinbase to report $581.2 million in revenue and earnings per share of -$2.44 with adjusted EBITDA of -$201.8 million driven by 8.4 million monthly transaction users (MTUs), according to data provided by Yahoo Finance.Before its Q4 earnings were released, Coinbase's stock had risen 86% year-to-date. Even with that rally, the value of Coinbase when measured on a per-share basis is still down significantly from its 52-week high of $206.79.That Coinbase beat revenue expectations is notable in that it came with declines in trading volume; Coinbase historically generated the bulk of its revenues from trading fees, making Q4 2022 notable. Consumer trading volumes fell from $26 billion in the third quarter of last year to $20 billion in Q4, while institutional volumes across the same timeframe fell from $133 billion to $125 billion.The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022, which resulted in Coinbase's total trading volumes and transaction revenues to fall 50% and 66% year-over-year, respectively, the company reported.As you would expect with declines in trading volume, trading revenue at Coinbase fell in Q4 compared to the third quarter of last year, dipping from $365.9 million to $322.1 million. (TechCrunch is comparing Coinbase's Q4 2022 results to Q3 2022 instead of Q4 2021, as the latter comparison would be less useful given how much the crypto market has changed in the last year; we're all aware that overall crypto activity has fallen from the final months of 2021.)There were bits of good news in the Coinbase report. While Coinbase's trading revenues were less than exuberant, the company's other revenues posted gains. What Coinbase calls its \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 of the same year, a gain of just over 34% in a single quarter.And even as the crypto industry faced a number of catastrophic events, including the Terra/LUNA and FTX collapses to name a few, there was still growth in other areas. The monthly active developers in crypto have more than doubled since 2020 to over 20,000, while major brands like Starbucks, Nike and Adidas have dived into the space alongside social media platforms like Instagram and Reddit.With big players getting into crypto, industry players are hoping this move results in greater adoption both for product use cases and trading volumes. Although there was a lot of movement from traditional retail markets and Web 2.0 businesses, trading volume for both consumer and institutional users fell quarter-over-quarter for Coinbase.Looking forward, it'll be interesting to see if these pieces pick back up and trading interest reemerges in 2023, or if platforms like Coinbase will have to keep looking elsewhere for revenue (like its subscription service) if users continue to shy away from the market.\n", 96 | "'''\n", 97 | "facts = fact_extraction_chain.run(article)\n", 98 | "\n", 99 | "print(facts)" 100 | ] 101 | }, 102 | { 103 | "attachments": {}, 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "## Phase 02 - Combine the Facts LLMChain with Summary Generation" 108 | ] 109 | }, 110 | { 111 | "attachments": {}, 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "#### Rewrite as a summary from the facts" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 6, 121 | "metadata": {}, 122 | "outputs": [ 123 | { 124 | "data": { 125 | "text/plain": [ 126 | "' the start of 2022.\\n\\nCoinbase released its Q4 2022 earnings on Tuesday, reporting total revenue of $605 million, which was slightly above Wall Street\\'s expectations of $581.2 million. Despite the positive revenue figure, Coinbase reported a GAAP loss of $557 million in the three-month period. Coinbase\\'s stock had risen 86% year-to-date before its Q4 earnings were released. Consumer trading volumes fell from $26 billion in Q3 2022 to $20 billion in Q4 2022, while institutional volumes across the same timeframe fell from $133 billion to $125 billion. The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022, leading to a 50% and 66% year-over-year decline in Coinbase\\'s total trading volumes and transaction revenues, respectively. Trading revenue at Coinbase fell from $365.9 million in Q3 2022 to $322.1 million in Q4 2022, while its \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 2022. Despite the overall decline in the crypto market, monthly active developers in crypto have more than doubled since the start of 2022.'" 127 | ] 128 | }, 129 | "execution_count": 6, 130 | "metadata": {}, 131 | "output_type": "execute_result" 132 | } 133 | ], 134 | "source": [ 135 | "prompt_02 = \"You are a Goldman Sachs analyst. Take the following list of facts and use them to write a short paragrah for investors. Don't leave out key info:\\n\\n {facts}\"\n", 136 | "summarty_gen_prompt = PromptTemplate(\n", 137 | " input_variables=[\"facts\"],\n", 138 | " template=prompt_02\n", 139 | " )\n", 140 | "\n", 141 | "summary_gen_chain = LLMChain(\n", 142 | " llm=llm,\n", 143 | " prompt=summarty_gen_prompt\n", 144 | " )\n", 145 | "\n", 146 | "summary = summary_gen_chain.run(facts)\n", 147 | "summary" 148 | ] 149 | }, 150 | { 151 | "attachments": {}, 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Final Lap - Chaining these together" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 7, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "from langchain.chains import SimpleSequentialChain, SequentialChain\n", 165 | "\n", 166 | "full_chain = SimpleSequentialChain(\n", 167 | " chains=[\n", 168 | " fact_extraction_chain,\n", 169 | " summary_gen_chain\n", 170 | " ],\n", 171 | " verbose=True\n", 172 | " )" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 8, 178 | "metadata": {}, 179 | "outputs": [ 180 | { 181 | "name": "stdout", 182 | "output_type": "stream", 183 | "text": [ 184 | "\n", 185 | "\n", 186 | "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n", 187 | "\u001b[36;1m\u001b[1;3m\n", 188 | "1. Coinbase released its Q4 2022 earnings on Tuesday.\n", 189 | "2. Coinbase generated $605 million in total revenue in Q4 2022.\n", 190 | "3. Coinbase lost $557 million in the three-month period on a GAAP basis.\n", 191 | "4. Wall Street expected Coinbase to report $581.2 million in revenue.\n", 192 | "5. Coinbase's stock had risen 86% year-to-date before its Q4 earnings were released.\n", 193 | "6. Consumer trading volumes fell from $26 billion in Q3 2022 to $20 billion in Q4 2022.\n", 194 | "7. Institutional volumes across the same timeframe fell from $133 billion to $125 billion.\n", 195 | "8. The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022.\n", 196 | "9. Coinbase's total trading volumes and transaction revenues fell 50% and 66% year-over-year, respectively.\n", 197 | "10. Trading revenue at Coinbase fell from $365.9 million in Q3 2022 to $322.1 million in Q4 2022.\n", 198 | "11. Coinbase's \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 2022.\n", 199 | "12. Monthly active developers in crypto have more than doubled since\u001b[0m\n", 200 | "\u001b[33;1m\u001b[1;3m the start of 2022.\n", 201 | "\n", 202 | "Coinbase released its Q4 2022 earnings on Tuesday, reporting total revenue of $605 million, which was slightly above Wall Street's expectations of $581.2 million. Despite the positive revenue figure, Coinbase reported a GAAP loss of $557 million in the three-month period. Coinbase's stock had risen 86% year-to-date before its Q4 earnings were released. Consumer trading volumes fell from $26 billion in Q3 2022 to $20 billion in Q4 2022, while institutional volumes across the same timeframe fell from $133 billion to $125 billion. The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022, leading to a 50% and 66% year-over-year decline in Coinbase's total trading volumes and transaction revenues, respectively. Trading revenue at Coinbase fell from $365.9 million in Q3 2022 to $322.1 million in Q4 2022, while its \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 2022. Despite the overall decline in the crypto market, monthly active developers in crypto have more than doubled since the start of 2022.\u001b[0m\n", 203 | "\n", 204 | "\u001b[1m> Finished chain.\u001b[0m\n" 205 | ] 206 | }, 207 | { 208 | "data": { 209 | "text/plain": [ 210 | "' the start of 2022.\\n\\nCoinbase released its Q4 2022 earnings on Tuesday, reporting total revenue of $605 million, which was slightly above Wall Street\\'s expectations of $581.2 million. Despite the positive revenue figure, Coinbase reported a GAAP loss of $557 million in the three-month period. Coinbase\\'s stock had risen 86% year-to-date before its Q4 earnings were released. Consumer trading volumes fell from $26 billion in Q3 2022 to $20 billion in Q4 2022, while institutional volumes across the same timeframe fell from $133 billion to $125 billion. The overall crypto market capitalization fell about 64%, or $1.5 trillion during 2022, leading to a 50% and 66% year-over-year decline in Coinbase\\'s total trading volumes and transaction revenues, respectively. Trading revenue at Coinbase fell from $365.9 million in Q3 2022 to $322.1 million in Q4 2022, while its \"subscription and services revenue\" rose from $210.5 million in Q3 2022 to $282.8 million in Q4 2022. Despite the overall decline in the crypto market, monthly active developers in crypto have more than doubled since the start of 2022.'" 211 | ] 212 | }, 213 | "execution_count": 8, 214 | "metadata": {}, 215 | "output_type": "execute_result" 216 | } 217 | ], 218 | "source": [ 219 | "response = full_chain.run(article)\n", 220 | "response" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [] 229 | } 230 | ], 231 | "metadata": { 232 | "kernelspec": { 233 | "display_name": "torch113", 234 | "language": "python", 235 | "name": "python3" 236 | }, 237 | "language_info": { 238 | "codemirror_mode": { 239 | "name": "ipython", 240 | "version": 3 241 | }, 242 | "file_extension": ".py", 243 | "mimetype": "text/x-python", 244 | "name": "python", 245 | "nbconvert_exporter": "python", 246 | "pygments_lexer": "ipython3", 247 | "version": "3.8.16" 248 | }, 249 | "orig_nbformat": 4 250 | }, 251 | "nbformat": 4, 252 | "nbformat_minor": 2 253 | } 254 | --------------------------------------------------------------------------------