Commit 5eaaba41 authored by Rayyyyy's avatar Rayyyyy
Browse files

First add in 0524

parents
Pipeline #1017 failed with stages
in 0 seconds
## [VideoSummary](VideoSummary.ipynb): Ask Llama 3 to Summarize a Long YouTube Video (using Replicate or [OctoAI](../llama_api_providers/OctoAI_API_examples/VideoSummary.ipynb))
This demo app uses Llama 3 to return a text summary of a YouTube video. It shows how to retrieve the caption of a YouTube video and how to ask Llama to summarize the content in different ways, from the simplest naive way that works for short text to more advanced methods of using LangChain's map_reduce and refine to overcome the 8K context length limit of Llama 3.
## [NBA2023-24](./text2sql/StructuredLlama.ipynb): Ask Llama 3 about Structured Data
This demo app shows how to use LangChain and Llama 3 to let users ask questions about **structured** data stored in a SQL DB. As the 2023-24 NBA season is entering the playoff, we use the NBA roster info saved in a SQLite DB to show you how to ask Llama 3 questions about your favorite teams or players.
## [LiveData](LiveData.ipynb): Ask Llama 3 about Live Data (using Replicate or [OctoAI](../llama_api_providers/OctoAI_API_examples/LiveData.ipynb))
This demo app shows how to perform live data augmented generation tasks with Llama 3, [LlamaIndex](https://github.com/run-llama/llama_index), another leading open-source framework for building LLM apps, and the [Tavily](https://tavily.com) live search API.
## [WhatsApp Chatbot](./chatbots/whatsapp_llama/whatsapp_llama3.md): Building a Llama 3 Enabled WhatsApp Chatbot
This step-by-step tutorial shows how to use the [WhatsApp Business API](https://developers.facebook.com/docs/whatsapp/cloud-api/overview) to build a Llama 3 enabled WhatsApp chatbot.
## [Messenger Chatbot](./chatbots/messenger_llama/messenger_llama3.md): Building a Llama 3 Enabled Messenger Chatbot
This step-by-step tutorial shows how to use the [Messenger Platform](https://developers.facebook.com/docs/messenger-platform/overview) to build a Llama 3 enabled Messenger chatbot.
### RAG Chatbot Example (running [locally](./chatbots/RAG_chatbot/RAG_Chatbot_Example.ipynb) or on [OctoAI](../llama_api_providers/OctoAI_API_examples/RAG_Chatbot_example/RAG_Chatbot_Example.ipynb))
A complete example of how to build a Llama 3 chatbot hosted on your browser that can answer questions based on your own data using retrieval augmented generation (RAG). You can run Llama2 locally if you have a good enough GPU or on OctoAI if you follow the note [here](../README.md#octoai_note).
## [Sales Bot](./chatbots/sales_bot/SalesBot.ipynb): Sales Bot with Llama3 - A Summarization and RAG Use Case
An summarization + RAG use case built around the Amazon product review Kaggle dataset to build a helpful Music Store Sales Bot. The summarization and RAG are built on top of Llama models hosted on OctoAI, and the vector database is hosted on Weaviate Cloud Services.
## [Media Generation](./MediaGen.ipynb): Building a Video Generation Pipeline with Llama3
This step-by-step tutorial shows how to use leverage Llama 3 to drive the generation of animated videos using SDXL and SVD. More specifically it relies on JSON formatting to produce a scene-by-scene story board of a recipe video. The user provides the name of a dish, then Llama 3 describes a step by step guide to reproduce the said dish. This step by step guide is brought to life with models like SDXL and SVD.
{
"cells": [
{
"cell_type": "markdown",
"id": "30b1235c-2f3e-4628-9c90-30385f741550",
"metadata": {},
"source": [
"<a href=\"https://colab.research.google.com/github/meta-llama/llama-recipes/blob/main/recipes/use_cases/VideoSummary.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n",
"\n",
"## This demo app shows:\n",
"* How to use LangChain's YoutubeLoader to retrieve the caption in a YouTube video\n",
"* How to ask Llama 3 to summarize the content (per the Llama's input size limit) of the video in a naive way using LangChain's stuff method\n",
"* How to bypass the limit of Llama 3's 8k context length limit by using a more sophisticated way using LangChain's `refine` and `map_reduce` methods - see [here](https://python.langchain.com/docs/use_cases/summarization) for more info"
]
},
{
"cell_type": "markdown",
"id": "c866f6be",
"metadata": {},
"source": [
"We start by installing the necessary packages:\n",
"- [youtube-transcript-api](https://pypi.org/project/youtube-transcript-api/) API to get transcript/subtitles of a YouTube video\n",
"- [langchain](https://python.langchain.com/docs/get_started/introduction) provides necessary RAG tools for this demo\n",
"- [tiktoken](https://github.com/openai/tiktoken) BytePair Encoding tokenizer\n",
"- [pytube](https://pytube.io/en/latest/) Utility for downloading YouTube videos"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "02482167",
"metadata": {},
"outputs": [],
"source": [
"!pip install langchain youtube-transcript-api tiktoken pytube replicate"
]
},
{
"cell_type": "markdown",
"id": "af3069b1",
"metadata": {},
"source": [
"Let's first load a long (2:47:16) YouTube video (Lex Fridman with Yann Lecun: Meta AI, Open Source, Limits of LLMs, AGI & the Future of AI) transcript using the YoutubeLoader."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3e4b8598",
"metadata": {},
"outputs": [],
"source": [
"from langchain.document_loaders import YoutubeLoader\n",
"\n",
"loader = YoutubeLoader.from_youtube_url(\n",
" \"https://www.youtube.com/watch?v=5t1vTLU7s40\", add_video_info=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dca32ebb",
"metadata": {},
"outputs": [],
"source": [
"# load the youtube video caption into Documents\n",
"docs = loader.load()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "afba128f-b7fd-4b2f-873f-9b5163455d54",
"metadata": {},
"outputs": [],
"source": [
"# check how many characters in the doc and some content\n",
"len(docs[0].page_content), docs[0].page_content[:300], len(docs)"
]
},
{
"cell_type": "markdown",
"id": "81748b73-0187-4487-ae89-a9429b580faa",
"metadata": {},
"source": [
"You should see 142689 returned for the doc character length, which is about 30k words or 40k tokens, beyond the 8k context length limit of Llama 3. You'll see how to summarize a text longer than the limit."
]
},
{
"cell_type": "markdown",
"id": "4af7cc16",
"metadata": {},
"source": [
"**Note:** We will be using [Replicate](https://replicate.com/meta/meta-llama-3-8b-instruct) to run the examples here. You will need to first sign in with Replicate with your github account, then create a free API token [here](https://replicate.com/account/api-tokens) that you can use for a while. You can also use other Llama 3 cloud providers such as [Groq](https://console.groq.com/), [Together](https://api.together.xyz/playground/language/meta-llama/Llama-3-8b-hf), or [Anyscale](https://app.endpoints.anyscale.com/playground) - see Section 2 of the Getting to Know Llama [notebook](https://github.com/meta-llama/llama-recipes/blob/main/recipes/quickstart/Getting_to_know_Llama.ipynb) for more info.\n",
"\n",
"If you'd like to run Llama 3 locally for the benefits of privacy, no cost or no rate limit (some Llama 3 hosting providers set limits for free plan of queries or tokens per second or minute), see [Running Llama Locally](https://github.com/meta-llama/llama-recipes/blob/main/recipes/quickstart/Running_Llama2_Anywhere/Running_Llama_on_Mac_Windows_Linux.ipynb)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab3ac00e",
"metadata": {},
"outputs": [],
"source": [
"# enter your Replicate API token, or you can use local Llama. See README for more info\n",
"from getpass import getpass\n",
"import os\n",
"\n",
"REPLICATE_API_TOKEN = getpass()\n",
"os.environ[\"REPLICATE_API_TOKEN\"] = REPLICATE_API_TOKEN\n"
]
},
{
"cell_type": "markdown",
"id": "6b911efd",
"metadata": {},
"source": [
"Next you'll call the Llama 3 70b chat model from Replicate because it's more powerful than the Llama 3 8b chat model when summarizing long text. You may also try Llama 3 8b model by replacing the `model` name with \"meta/meta-llama-3-8b-instruct\"."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "adf8cf3d",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.llms import Replicate\n",
"llm = Replicate(\n",
" model=\"meta/meta-llama-3-70b-instruct\",\n",
" model_kwargs={\"temperature\": 0.0, \"top_p\": 1, \"max_new_tokens\":1000}\n",
")"
]
},
{
"cell_type": "markdown",
"id": "8e3baa56",
"metadata": {},
"source": [
"Once everything is set up, you can prompt Llama 3 to summarize the first 4000 characters of the transcript. \n",
"\n",
"**Note:** The context length of 8k tokens in Llama 3 is roughly 6000-7000 words or 32k characters, so you should be able to use a number larger than 4000."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51739e11",
"metadata": {},
"outputs": [],
"source": [
"text = docs[0].page_content[:4000]\n",
"summary = llm.invoke(f\"Give me a summary of the text below: {text}.\")\n",
"print(summary)"
]
},
{
"cell_type": "markdown",
"id": "5cb1fc2a-71cc-4fda-9d0b-2765a266dee7",
"metadata": {},
"source": [
"You can try a larger text to see how the summary differs."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f049cf9c-528e-4786-93b0-756575be92fb",
"metadata": {},
"outputs": [],
"source": [
"text = docs[0].page_content[:10000]\n",
"summary = llm.invoke(f\"Give me a summary of the text below: {text}.\")\n",
"print(summary)"
]
},
{
"cell_type": "markdown",
"id": "d6f3ef40-7cce-4b74-9c66-7bb769650760",
"metadata": {},
"source": [
"If you try the whole content which has over 142k characters, about 40k tokens, which exceeds the 8k limit, you'll get an empty result (Replicate used to return an error \"RuntimeError: Your input is too long.\")."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0ba1ecca-6d0c-495f-a398-df5be119b5cb",
"metadata": {},
"outputs": [],
"source": [
"# this will generate an empty result because the input exceeds Llama 3's context length limit\n",
"text = docs[0].page_content\n",
"summary = llm.invoke(f\"Give me a summary of the text below: {text}.\")\n",
"print(summary)"
]
},
{
"cell_type": "markdown",
"id": "1ad1881a",
"metadata": {},
"source": [
"To fix this, you can use LangChain's `load_summarize_chain` method (detail [here](https://python.langchain.com/docs/use_cases/summarization)). \n",
"\n",
"First you'll create splits or sub-documents of the original content, then use the LangChain's `load_summarize_chain` with the `refine` or `map_reduce` type. \n",
"\n",
"Because this may involve many calls to Llama 3, it'd be great to set up a quick free LangChain API key [here](https://smith.langchain.com/settings), run the following cell to set up necessary environment variables, and check the logs on [LangSmith](https://docs.smith.langchain.com) during and after the run."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d436a764-181f-459d-ac00-ea8ea4e9a831",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"os.environ[\"LANGCHAIN_API_KEY\"] = \"your_langchain_api_key\"\n",
"os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"os.environ[\"LANGCHAIN_PROJECT\"] = \"Video Summary with Llama 3\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3be1236a-fe6a-4bf6-983f-0e72dde39fee",
"metadata": {},
"outputs": [],
"source": [
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"\n",
"# we need to split the long input text\n",
"text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(\n",
" chunk_size=1000, chunk_overlap=0\n",
")\n",
"split_docs = text_splitter.split_documents(docs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "12ae9e9d-3434-4a84-a298-f2b98de9ff01",
"metadata": {},
"outputs": [],
"source": [
"# check the splitted docs lengths\n",
"len(split_docs), len(docs), len(split_docs[0].page_content), len(docs[0].page_content)"
]
},
{
"cell_type": "markdown",
"id": "0352a0ec-4d40-4ac1-a46a-b121eacb593e",
"metadata": {},
"source": [
"The `refine` type implements the following steps under the hood:\n",
"\n",
"1. Call Llama 3 on the first sub-document to generate a concise summary;\n",
"2. Loop over each subsequent sub-document, pass the previous summary with the current sub-document to generate a refined new summary;\n",
"3. Return the final summary generated on the final sub-document as the final answer - the summary of the whole content.\n",
"\n",
"An example prompt template for each call in step 2, which gets used under the hood by LangChain, is:\n",
"```\n",
"Your job is to produce a final summary.\n",
"We have provided an existing summary up to a certain point:\n",
"<previous_summary>\n",
"Refine the existing summary (only if needed) with some more content below:\n",
"<new_content>\n",
"```\n",
"\n",
"**Note:** The following call will make 33 calls to Llama 3 and genereate the final summary in about 10 minutes. The complete log of the the calls with inputs and outputs is [here](https://smith.langchain.com/public/7f23d823-926f-4874-bbd7-b509328a94bf/r)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "127f17fe-d5b7-43af-bd2f-2b47b076d0b1",
"metadata": {},
"outputs": [],
"source": [
"from langchain.chains.summarize import load_summarize_chain\n",
"\n",
"chain = load_summarize_chain(llm, chain_type=\"refine\")\n",
"chain.run(split_docs)"
]
},
{
"cell_type": "markdown",
"id": "c3976c92",
"metadata": {},
"source": [
"You can also set `chain_type` to [`map_reduce`](https://python.langchain.com/docs/modules/chains/document/map_reduce) to generate the summary of the entire content using the standard map and reduce method, which works behind the scene by first mapping each split document to a sub-summary via a call to LLM, then combines all those sub-summaries into a single final summary by yet another call to LLM.\n",
"\n",
"**Note:** The following call takes about 3 minutes and all the calls to Llama 3 with inputs and outputs can be traced [here](https://smith.langchain.com/public/e54fad15-91ad-44a0-8d8f-f27a0d880b04/r)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8991df49-8578-46de-8b30-cb2cd11e30f1",
"metadata": {},
"outputs": [],
"source": [
"chain = load_summarize_chain(llm, chain_type=\"map_reduce\")\n",
"chain.run(split_docs)"
]
},
{
"cell_type": "markdown",
"id": "e1b87c24-207e-403b-b534-20f24a142f53",
"metadata": {},
"source": [
"One final `chain_type` you can set is `stuff`, but it won't work with large documents because it stuffs all the split documents into one and uses it in a single prompt which exceeds the Llama 3 context length limit."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ccd48de3-5387-4eba-8b2f-097bfac7dbbc",
"metadata": {},
"outputs": [],
"source": [
"# this will return nothing\n",
"chain = load_summarize_chain(llm, chain_type=\"stuff\")\n",
"chain.run(split_docs)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
# LangChain <> Llama3 Cookbooks
LLM agents use [planning, memory, and tools](https://lilianweng.github.io/posts/2023-06-23-agent/) to accomplish tasks. Agents can empower Llama 3 with important new capabilities. Here, we will show how to give Llama 3 the ability to perform web search, as well as multi-modality: image generation (text-to-image), image analysis (image-to-text), and voice (text-to-speech) tools!
LangChain offers several different ways to implement agents with Llama 3:
(1) `ReAct agent` - Uses [AgentExecutor](https://python.langchain.com/docs/modules/agents/quick_start/) with [tool-calling](https://python.langchain.com/docs/integrations/chat/) versions of Llama 3.
(2) `LangGraph tool calling agent` - Uses [LangGraph](https://python.langchain.com/docs/langgraph) with [tool-calling](https://python.langchain.com/docs/integrations/chat/) versions of Llama 3.
(3) `LangGraph custom agent` - Uses [LangGraph](https://python.langchain.com/docs/langgraph) with **any** version of Llama 3 (so long as it supports structured output).
As we move from option (1) to (3) the degree of customization and flexibility increases:
(1) `ReAct agent` using AgentExecutor is a great for getting started quickly with minimal code, but requires a version of Llama 3 with reliable tool-calling, is the least customizable, and uses higher-level AgentExecutor abstraction.
(2) `LangGraph tool calling agent` is more customizable than (1) because the LLM assistant (planning) and tool call (action) nodes are defined by the user, but it still requires a version of Llama 3 with reliable tool-calling.
(3) `LangGraph custom agent` does not require a version of Llama 3 with reliable tool-calling and is the most customizable, but requires the most work to implement.
![langgraph_agent_architectures](https://github.com/rlancemartin/llama-recipes/assets/122662504/5ed2bef0-ae11-4efa-9e88-ab560a4d0022)
---
### `ReAct agent`
The AgentExecutor manages the loop of planning, executing tool calls, and processing outputs until an AgentFinish signal is generated, indicating task completion.
Our first notebook, `tool-calling-agent`, shows how to build a [tool calling agent](https://python.langchain.com/docs/modules/agents/agent_types/tool_calling/) with AgentExecutor and Llama 3.
---
### `LangGraph tool calling agent`
[LangGraph](https://python.langchain.com/docs/langgraph) is a library from LangChain that can be used to build reliable agents.
Our second notebook, `langgraph-tool-calling-agent`, shows an alternative to AgentExecutor for building a Llama 3 powered agent.
---
### `LangGraph custom agent`
Our third notebook, `langgraph-custom-agent`, shows how to build a Llama 3 powered agent without reliance on tool-calling.
---
### `LangGraph RAG Agent`
Our fourth notebook, `langgraph-rag-agent`, shows how to apply LangGraph to build a custom Llama 3 powered RAG agent that use ideas from 3 papers:
* Corrective-RAG (CRAG) [paper](https://arxiv.org/pdf/2401.15884.pdf) uses self-grading on retrieved documents and web-search fallback if documents are not relevant.
* Self-RAG [paper](https://arxiv.org/abs/2310.11511) adds self-grading on generations for hallucinations and for ability to answer the question.
* Adaptive RAG [paper](https://arxiv.org/abs/2403.14403) routes queries between different RAG approaches based on their complexity.
We implement each approach as a control flow in LangGraph:
- **Planning:** The sequence of RAG steps (e.g., retrieval, grading, and generation) that we want the agent to take.
- **Memory:** All the RAG-related information (input question, retrieved documents, etc) that we want to pass between steps.
- **Tool use:** All the tools needed for RAG (e.g., decide web search or vectorstore retrieval based on the question).
We will build from CRAG (blue, below) to Self-RAG (green) and finally to Adaptive RAG (red):
![langgraph_rag_agent_](https://github.com/rlancemartin/llama-recipes/assets/122662504/ec4aa1cd-3c7e-4cd1-a1e7-7deddc4033a8)
---
### `Local LangGraph RAG Agent`
Our fifth notebook, `langgraph-rag-agent-local`, shows how to apply LangGraph to build advanced RAG agents using Llama 3 that run locally and reliably.
See this [video overview](https://www.youtube.com/watch?v=sgnrL7yo1TE) for more detail on the design of this agent.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Building a Meta Llama 3 chatbot with Retrieval Augmented Generation (RAG)\n",
"\n",
"This notebook shows a complete example of how to build a Meta Llama 3 chatbot hosted on your browser that can answer questions based on your own data. We'll cover:\n",
"* The deployment process of Meta Llama 3 8B with the [Text-generation-inference](https://github.com/huggingface/text-generation-inference) framework as an API server\n",
"* A chatbot example built with [Gradio](https://github.com/gradio-app/gradio) and wired to the server\n",
"* Adding RAG capability with Meta Llama 3 specific knowledge based on our Getting Started [guide](https://ai.meta.com/llama/get-started/)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## RAG Architecture\n",
"\n",
"LLMs have unprecedented capabilities in NLU (Natural Language Understanding) & NLG (Natural Language Generation), but they have a knowledge cutoff date, and are only trained on publicly available data before that date.\n",
"\n",
"RAG, invented by [Meta](https://ai.meta.com/blog/retrieval-augmented-generation-streamlining-the-creation-of-intelligent-natural-language-processing-models/) in 2020, is one of the most popular methods to augment LLMs. RAG allows enterprises to keep sensitive data on-prem and get more relevant answers from generic models without fine-tuning models for specific roles.\n",
"\n",
"RAG is a method that:\n",
"* Retrieves data from outside a foundation model\n",
"* Augments your questions or prompts to LLMs by adding the retrieved relevant data as context\n",
"* Allows LLMs to answer questions about your own data, or data not publicly available when LLMs were trained\n",
"* Greatly reduces the hallucination in model's response generation\n",
"\n",
"The following diagram shows the general RAG components and process:"
]
},
{
"attachments": {
"image.png": {
"image/png": "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"
}
},
"cell_type": "markdown",
"metadata": {},
"source": [
"![image.png](attachment:image.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## How to Develop a RAG Powered Meta Llama 3 Chatbot\n",
"\n",
"The easiest way to develop RAG-powered Meta Llama 3 chatbots is to use frameworks such as [**LangChain**](https://www.langchain.com/) and [**LlamaIndex**](https://www.llamaindex.ai/), two leading open-source frameworks for building LLM apps. Both offer convenient APIs for implementing RAG with Meta Llama 3 including:\n",
"\n",
"* Load and split documents\n",
"* Embed and store document splits\n",
"* Retrieve the relevant context based on the user query\n",
"* Call Meta Llama 3 with query and context to generate the answer\n",
"\n",
"LangChain is a more general purpose and flexible framework for developing LLM apps with RAG capabilities, while LlamaIndex as a data framework focuses on connecting custom data sources to LLMs. The integration of the two may provide the best performant and effective solution to building real world RAG apps. \n",
"In our example, for simplicifty, we will use LangChain alone with locally stored PDF data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Install Dependencies\n",
"\n",
"For this demo, we will be using the Gradio for chatbot UI, Text-generation-inference framework for model serving. \n",
"For vector storage and similarity search, we will be using [FAISS](https://github.com/facebookresearch/faiss). \n",
"In this example, we will be running everything in a AWS EC2 instance (i.e. [g5.2xlarge]( https://aws.amazon.com/ec2/instance-types/g5/)). g5.2xlarge features one A10G GPU. We recommend running this notebook with at least one GPU equivalent to A10G with at least 16GB video memory. \n",
"There are certain techniques to downsize the Meta Llama 3 8B model, so it can fit into smaller GPUs. But it is out of scope here.\n",
"\n",
"First, let's install all dependencies with PIP. We also recommend you start a dedicated Conda environment for better package management"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip install -r requirements.txt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Data Processing\n",
"\n",
"First run all the imports and define the path of the data and vector storage after processing. \n",
"For the data, we will be using a raw pdf crawled from Meta Llama 3 Getting Started guide on [Meta AI website](https://ai.meta.com/llama/)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from langchain.embeddings import HuggingFaceEmbeddings\n",
"from langchain.vectorstores import FAISS\n",
"from langchain.document_loaders import PyPDFDirectoryLoader\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter \n",
"\n",
"DATA_PATH = 'data' #Your root data folder path\n",
"DB_FAISS_PATH = 'vectorstore/db_faiss'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we use the `PyPDFDirectoryLoader` to load the entire directory. You can also use `PyPDFLoader` for loading one single file."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"loader = PyPDFDirectoryLoader(DATA_PATH)\n",
"documents = loader.load()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check the length and content of the doc to ensure we have loaded the right document with number of pages as 37."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"37 11/8/23, 2:00 PM Getting started with Llama 2 - AI at Meta\n",
"https://ai.meta.com/llama/get-started/ 1/\n"
]
}
],
"source": [
"print(len(documents), documents[0].page_content[0:100])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Split the loaded documents into smaller chunks. \n",
"[`RecursiveCharacterTextSplitter`](https://api.python.langchain.com/en/latest/text_splitter/langchain.text_splitter.RecursiveCharacterTextSplitter.html) is one common splitter that splits long pieces of text into smaller, semantically meaningful chunks. \n",
"Other splitters include:\n",
"* SpacyTextSplitter\n",
"* NLTKTextSplitter\n",
"* SentenceTransformersTokenTextSplitter\n",
"* CharacterTextSplitter\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"103 page_content='11/8/23, 2:00 PM Getting started with Llama 2 - AI at Meta\\nhttps://ai.meta.com/llama/get-started/ 1/37\\nLlama 2 Get Started FAQ Download the Model\\nQuick setup and how-to guide\\nGetting started\\nwith Llama\\nWelcome to the getting started guide for Llama.\\nThis guide provides information and resources to help you set up Llama including how to access the model,\\nhosting, how-to and integration guides. Additionally , you will find supplemental materials to further assist you while\\nbuilding with Llama.' metadata={'source': 'data/Llama Getting Started Guide.pdf', 'page': 0}\n"
]
}
],
"source": [
"text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=10)\n",
"splits = text_splitter.split_documents(documents)\n",
"print(len(splits), splits[0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we have set `chunk_size` to 500 and `chunk_overlap` to 10. In the spliting, these two parameters can directly affects the quality of the LLM's answers. \n",
"Here is a good [guide](https://dev.to/peterabel/what-chunk-size-and-chunk-overlap-should-you-use-4338) on how you should carefully set these two parameters."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we will need to choose an embedding model for our splited documents. \n",
"**Embeddings are numerial representations of text**. The default embedding model in HuggingFace Embeddings is `sentence-transformers/all-mpnet-base-v2` with 768 dimension. Below we use a smaller model `all-MiniLM-L6-v2` with dimension 384 so indexing runs faster."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6070abfb657146febbbf5281a5b609e7",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"modules.json: 0%| | 0.00/349 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ffb9a713778a463db5a60db7939a4a20",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"config_sentence_transformers.json: 0%| | 0.00/116 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5d697da142ce4d7d9ef67580b5d22df8",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"README.md: 0%| | 0.00/10.7k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2169e09d68da4ab8a81a9776c6b8dc8c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"sentence_bert_config.json: 0%| | 0.00/53.0 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6f2fe9417d58428b96baf99c3714fd1b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"config.json: 0%| | 0.00/612 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b188185f84904c63958ed32edadc2497",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors: 0%| | 0.00/90.9M [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0b0238093bea427da26a844ed5a42b4a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer_config.json: 0%| | 0.00/350 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "00f52d8e73d3494ca268847f562bcff3",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"vocab.txt: 0%| | 0.00/232k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f58d105e7e4d471b952171c1f5a20319",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.json: 0%| | 0.00/466k [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "201e429b6a15437b982408b8a8e0530c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"special_tokens_map.json: 0%| | 0.00/112 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7410488fbd86491fadcbc7fd26a92078",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"1_Pooling/config.json: 0%| | 0.00/190 [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"embeddings = HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2',\n",
" model_kwargs={'device': 'cuda'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lastly, with splits and choice of the embedding model ready, we want to index them and store all the split chunks as embeddings into the vector storage. \n",
"\n",
"Vector stores are databases storing embeddings. There're at least 60 [vector stores](https://python.langchain.com/docs/integrations/vectorstores) supported by LangChain, and two of the most popular open source ones are:\n",
"* [Chroma](https://www.trychroma.com/): a light-weight and in memory so it's easy to get started with and use for **local development**.\n",
"* [FAISS](https://python.langchain.com/docs/integrations/vectorstores/faiss) (Facebook AI Similarity Search): a vector store that supports search in vectors that may not fit in RAM and is appropriate for **production use**. \n",
"\n",
"Since we are running on a EC2 instance with abundant CPU resources and RAM, we will use FAISS in this example. Note that FAISS can also run on GPUs, where some of the most useful algorithms are implemented there. In that case, install `faiss-gpu` package with PIP instead."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"db = FAISS.from_documents(splits, embeddings)\n",
"db.save_local(DB_FAISS_PATH)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once you saved database into local path. You can find them as `index.faiss` and `index.pkl`. In the chatbot example, you can then load this database from local and plug it into our retrival process."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Model Serving\n",
"\n",
"In this example, we will be deploying a Meta Llama 3 8B chat HuggingFace model with the Text-generation-inference framework on-permises. \n",
"This would allow us to directly wire the API server with our chatbot. \n",
"There are alternative solutions to deploy Meta Llama 3 models on-permises as your local API server. \n",
"You can find our complete guide [here](https://github.com/meta-llama/llama-recipes/blob/main/recipes/inference/model_servers/llama-on-prem.md)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In a **separate terminal**, run commands below to launch an API server with TGI. This will download model artifacts and store them locally, while launching at the desire port on your localhost. In our case, this is port 8080"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model=meta-llama/Meta-Llama-3-8B-Instruct\n",
"volume=$PWD/data # share a volume with the Docker container to avoid downloading weights every run\n",
"token=#your-huggingface-token\n",
"docker run --gpus all --shm-size 1g -e HUGGING_FACE_HUB_TOKEN=$token -p 8080:80 -v $volume:/data ghcr.io/huggingface/text-generation-inference:2.0 --model-id $model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once we have the API server up and running, we can run a simple `curl` command to validate our model is working as expected."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!curl localhost:8080/generate -X POST -H 'Content-Type: application/json' -d '{\"inputs\": \"What is good about Beijing?\", \"parameters\": { \"max_new_tokens\":64}}' #Replace the locahost with the IP visible to the machine running the notebook "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Building the Chatbot UI\n",
"\n",
"Now we are ready to build the chatbot UI to wire up RAG data and API server. In our example we will be using Gradio to build the Chatbot UI. \n",
"Gradio is an open-source Python library that is used to build machine learning and data science demos and web applications. It had been widely used by the community and HuggingFace also used Gradio to build their Chatbots. Other alternatives are: \n",
"* [Streamlit](https://streamlit.io/)\n",
"* [Dash](https://plotly.com/dash/)\n",
"* [Flask](https://flask.palletsprojects.com/en/3.0.x/)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we start by adding all the imports, paths, constants and set LangChain in debug mode, so it shows clear actions within the chain process."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import langchain\n",
"from queue import Queue\n",
"from typing import Any\n",
"from langchain.llms.huggingface_text_gen_inference import HuggingFaceTextGenInference\n",
"from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n",
"from langchain.schema import LLMResult\n",
"from langchain.embeddings import HuggingFaceEmbeddings\n",
"from langchain.vectorstores import FAISS\n",
"from langchain.chains import RetrievalQA\n",
"from langchain.prompts.prompt import PromptTemplate\n",
"from anyio.from_thread import start_blocking_portal #For model callback streaming\n",
"\n",
"langchain.debug=True \n",
"\n",
"#vector db path\n",
"DB_FAISS_PATH = 'vectorstore/db_faiss'\n",
"\n",
"#Llama2 TGI models host port\n",
"LLAMA3_8B_HOSTPORT = \"http://localhost:8080/\" #Replace the locahost with the IP visible to the machine running the notebook\n",
"LLAMA3_70B_HOSTPORT = \"http://localhost:8081/\" # You can host multiple models if your infrastructure has capacity\n",
"\n",
"\n",
"model_dict = {\n",
" \"8b-instruct\" : LLAMA3_8B_HOSTPORT,\n",
" \"70b-instruct\" : LLAMA3_70B_HOSTPORT,\n",
"}\n",
"\n",
"system_message = {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we load the FAISS vector store"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"embeddings = HuggingFaceEmbeddings(model_name=\"sentence-transformers/all-MiniLM-L6-v2\",\n",
" model_kwargs={'device': 'cuda'})\n",
"db = FAISS.load_local(DB_FAISS_PATH, embeddings, allow_dangerous_deserialization=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we create a TGI llm instance and wire to the API serving port on localhost"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/conda/envs/pytorch/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The class `HuggingFaceTextGenInference` was deprecated in LangChain 0.0.21 and will be removed in 0.2.0. Use HuggingFaceEndpoint instead.\n",
" warn_deprecated(\n",
"/opt/conda/envs/pytorch/lib/python3.10/site-packages/pydantic/_internal/_fields.py:127: UserWarning: Field \"model_id\" has conflict with protected namespace \"model_\".\n",
"\n",
"You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.\n",
" warnings.warn(\n"
]
}
],
"source": [
"llm = HuggingFaceTextGenInference(\n",
" inference_server_url=LLAMA3_8B_HOSTPORT,\n",
" max_new_tokens=512,\n",
" top_k=10,\n",
" top_p=0.9,\n",
" typical_p=0.95,\n",
" temperature=0.6,\n",
" repetition_penalty=1,\n",
" do_sample=True,\n",
" streaming=True\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we define the retriever and template for our RetrivalQA chain. For each call of the RetrievalQA, LangChain performs a semantic similarity search of the query in the vector database, then passes the search results as the context to Llama to answer the query about the data stored in the verctor database. \n",
"Whereas for the template, this defines the format of the question along with context that we will be sent into Llama for generation. In general, Meta Llama 3 has special prompt format to handle special tokens. In some cases, the serving framework might already have taken care of it. Otherwise, you will need to write customized template to properly handle that.\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"system_prompt = \"\"\n",
"\n",
"template = \"\"\"\n",
"Use the following pieces of context to answer the question. If no context provided, answer like a AI assistant.\n",
"{context}\n",
"Question: {question}\n",
"\"\"\" \n",
"\n",
"retriever = db.as_retriever(\n",
" search_kwargs={\"k\": 6}\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lastly, we can define the retrieval chain for QA"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"qa_chain = RetrievalQA.from_chain_type(\n",
" llm=llm, \n",
" retriever=retriever, \n",
" chain_type_kwargs={\n",
" \"prompt\": PromptTemplate(\n",
" template=template,\n",
" input_variables=[\"context\", \"question\"],\n",
" ),\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we should have a working chain for QA. Let's test it out before wire it up with UI blocks."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"result = qa_chain({\"query\": \"Why choose Llama?\"})\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After confirming the validity, we can start building the UI. Before we define the gradio [blocks](https://www.gradio.app/docs/blocks), let's first define the callback streams that we will use later for the streaming feature. \n",
"This callback handler will put streaming LLM responses to a queue for gradio UI to render on the fly. "
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"job_done = object()\n",
"\n",
"class MyStream(StreamingStdOutCallbackHandler):\n",
" def __init__(self, q) -> None:\n",
" self.q = q\n",
"\n",
" def on_llm_new_token(self, token: str, **kwargs: Any) -> None:\n",
" self.q.put(token)\n",
"\n",
" def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:\n",
" self.q.put(job_done)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can define the gradio UI blocks. \n",
"Since we will need to define the UI and handlers in the same place, this will be a large chunk of code. We will add comments in the code for explanation."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"import gradio as gr\n",
"\n",
"with gr.Blocks() as demo:\n",
" #Configure UI layout\n",
" chatbot = gr.Chatbot(height = 600)\n",
" with gr.Row():\n",
" with gr.Column(scale=1):\n",
" with gr.Row():\n",
" #model selection\n",
" model_selector = gr.Dropdown(\n",
" list(model_dict.keys()), \n",
" value=\"7b-chat\", \n",
" label=\"Model\", \n",
" info=\"Select the model\", \n",
" interactive = True, \n",
" scale=1\n",
" )\n",
" max_new_tokens_selector = gr.Number(\n",
" value=512, \n",
" precision=0, \n",
" label=\"Max new tokens\", \n",
" info=\"Adjust max_new_tokens\",\n",
" interactive = True, \n",
" minimum=1, \n",
" maximum=1024, \n",
" scale=1\n",
" )\n",
" with gr.Row():\n",
" #hyperparameter selection\n",
" temperature_selector = gr.Slider(\n",
" value=0.6, \n",
" label=\"Temperature\", \n",
" info=\"Range 0-2. Controls the creativity of the generated text.\",\n",
" interactive = True, \n",
" minimum=0.01, \n",
" maximum=2, \n",
" step=0.01, \n",
" scale=1\n",
" )\n",
" top_p_selector = gr.Slider(\n",
" value=0.9, \n",
" label=\"Top_p\", \n",
" info=\"Range 0-1. Nucleus sampling.\",\n",
" interactive = True, \n",
" minimum=0.01, \n",
" maximum=0.99, \n",
" step=0.01, \n",
" scale=1\n",
" )\n",
" with gr.Column(scale=2):\n",
" #user input prompt text field\n",
" user_prompt_message = gr.Textbox(placeholder=\"Please add user prompt here\", label=\"User prompt\")\n",
" with gr.Row():\n",
" clear = gr.Button(\"Clear Conversation\", scale=2)\n",
" submitBtn = gr.Button(\"Submit\", scale=8)\n",
"\n",
"\n",
" state = gr.State([])\n",
"\n",
" #handle user message\n",
" def user(user_prompt_message, history):\n",
" if user_prompt_message != \"\":\n",
" return history + [[user_prompt_message, None]]\n",
" else:\n",
" return history + [[\"Invalid prompts - user prompt cannot be empty\", None]]\n",
"\n",
" #chatbot logic for configuration, sending the prompts, rendering the streamed back genereations etc\n",
" def bot(model_selector, temperature_selector, top_p_selector, max_new_tokens_selector, user_prompt_message, history, messages_history):\n",
" dialog = []\n",
" bot_message = \"\"\n",
" history[-1][1] = \"\"\n",
" \n",
" dialog = [\n",
" {\"role\": \"user\", \"content\": user_prompt_message},\n",
" ]\n",
" messages_history += dialog\n",
" \n",
" #Queue for streamed character rendering\n",
" q = Queue()\n",
"\n",
" #Update new llama hyperparameters\n",
" llm.inference_server_url = model_selector\n",
" llm.temperature = temperature_selector\n",
" llm.top_p = top_p_selector\n",
" llm.max_new_tokens = max_new_tokens_selector\n",
"\n",
" #Async task for streamed chain results wired to callbacks we previously defined, so we don't block the UI\n",
" async def task(prompt):\n",
" ret = await qa_chain.run(prompt, callbacks=[MyStream(q)])\n",
" return ret\n",
"\n",
" with start_blocking_portal() as portal:\n",
" portal.start_task_soon(task, user_prompt_message)\n",
" while True:\n",
" next_token = q.get(True)\n",
" if next_token is job_done:\n",
" messages_history += [{\"role\": \"assistant\", \"content\": bot_message}]\n",
" return history, messages_history\n",
" bot_message += next_token\n",
" history[-1][1] += next_token\n",
" yield history, messages_history\n",
"\n",
" #init the chat history with default system message \n",
" def init_history(messages_history):\n",
" messages_history = []\n",
" messages_history += [system_message]\n",
" return messages_history\n",
"\n",
" #clean up the user input text field\n",
" def input_cleanup():\n",
" return \"\"\n",
"\n",
" #when the user clicks Enter and the user message is submitted\n",
" user_prompt_message.submit(\n",
" user, \n",
" [user_prompt_message, chatbot], \n",
" [chatbot], \n",
" queue=False\n",
" ).then(\n",
" bot, \n",
" [model_selector, temperature_selector, top_p_selector, max_new_tokens_selector, user_prompt_message, chatbot, state], \n",
" [chatbot, state]\n",
" ).then(input_cleanup, \n",
" [], \n",
" [user_prompt_message], \n",
" queue=False\n",
" )\n",
"\n",
" #when the user clicks the submit button\n",
" submitBtn.click(\n",
" user, \n",
" [user_prompt_message, chatbot], \n",
" [chatbot], \n",
" queue=False\n",
" ).then(\n",
" bot, \n",
" [model_selector, temperature_selector, top_p_selector, max_new_tokens_selector, user_prompt_message, chatbot, state], \n",
" [chatbot, state]\n",
" ).then(\n",
" input_cleanup, \n",
" [], \n",
" [user_prompt_message], \n",
" queue=False\n",
" )\n",
" \n",
" #when the user clicks the clear button\n",
" clear.click(lambda: None, None, chatbot, queue=False).success(init_history, [state], [state])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lastly, we can launch this demo on our localhost with the command below. "
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running on local URL: http://0.0.0.0:7860\n",
"\n",
"To create a public link, set `share=True` in `launch()`.\n"
]
},
{
"data": {
"text/html": [
"<div><iframe src=\"http://localhost:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": []
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"demo.queue().launch(server_name=\"0.0.0.0\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Gradio will default the launch port to 7860. You can select which port it should launch on as needed. \n",
"Once launched, in the notebook or a browser with URL http://0.0.0.0:7860, you should see the UI. \n",
"Things to try in the chatbot demo: \n",
"* Asking specific questions related to the Meta Llama 3 Getting Started Guide\n",
"* Adjust parameters such as max new token generated\n",
"* Switching to another Llama model with another container launched in a separate terminal\n",
"\n",
"Once finished testing, make sure you close the demo by running the command below to release the port."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"demo.close()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "myenv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
gradio
pypdf
langchain
sentence-transformers
faiss-cpu
text-generation
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
# Copyright (c) Meta Platforms, Inc. and affiliates.
# This software may be used and distributed according to the terms of the Llama 3 Community License Agreement.
import langchain
from langchain.llms import Replicate
from flask import Flask
from flask import request
import os
import requests
import json
os.environ["REPLICATE_API_TOKEN"] = "<your replicate api token>"
llama3_8b_chat = "meta/meta-llama-3-8b-instruct"
llm = Replicate(
model=llama3_8b_chat,
model_kwargs={"temperature": 0.0, "top_p": 1, "max_new_tokens":500}
)
app = Flask(__name__)
@app.route('/msgrcvd_pager', methods=['POST', 'GET'])
def msgrcvd_pager():
message = request.args.get('message')
sender = request.args.get('sender')
recipient = request.args.get('recipient')
answer = llm(message)
print(message)
print(answer)
url = f"https://graph.facebook.com/v18.0/{recipient}/messages"
params = {
'recipient': '{"id": ' + sender + '}',
'message': json.dumps({'text': answer}),
'messaging_type': 'RESPONSE',
'access_token': "<your page access token>"
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, params=params, headers=headers)
print(response.status_code)
print(response.text)
return message + "<p/>" + answer
# Building a Llama 3 Enabled Messenger Chatbot
This step-by-step tutorial shows the complete process of building a Llama-enabled Messenger chatbot. A demo video of using the iOS Messenger app to send a question to a Facebook business page and receive the Llama 3 generated answer is [here](https://drive.google.com/file/d/1B4ijFH4X3jEHZfkGdTPmdsgpUes_RNud/view).
If you're interested in a Llama 3 enabled WhatsApp chatbot, see [here](../whatsapp_llama/whatsapp_llama3.md) for a tutorial.
## Overview
Messenger from Meta is a messaging service that allows a Facebook business page to respond to people who are interested in their business using [Messenger Platform](https://developers.facebook.com/docs/messenger-platform/overview). The benefits of an intelligent and knowledgable Llama 3 powered chatbot are obvious, including cost saving and better customer experience such as 24x7 availability. In this tutorial, we'll cover the details of integrating Llama 3 with the Messenger Platform to build a basic Llama 3 enabled chatbot - for more Llama 3 application development and deployment demos such as how to integrate your own data with Llama 3, see the recipes.
The diagram below shows the components and overall data flow of the Llama 3 enabled Messenger chatbot demo we built, using an Amazon EC2 instance as an example for running the web server.
![](../../../../docs/images/messenger_llama_arch.jpg)
## Getting Started with Messenger Platform
1. A Facebook Page is required to send and receive messages using the Messenger Platform - see [here](https://www.facebook.com/business/help/461775097570076?id=939256796236247) for details about Facebook Pages and how to create a new page.
2. If you have followed the [Llama WhatsApp chatbot tutorial](../whatsapp_llama/whatsapp_llama3.md), or if you already have a Meta developer account and a business app, then you can skip this step. Otherwise, you need to first [create a Meta developer account](https://developers.facebook.com/) and then [create a business app](https://developers.facebook.com/docs/development/create-an-app/).
3. Add the Messenger product to your business app by going to your business app's Dashboard, click "Add Product" and then select "Messenger".
4. Configure a webhook to receive real time HTTP notifications: follow the [Sample Callback URL for Webhooks Testing Guide](https://developers.facebook.com/docs/whatsapp/sample-app-endpoints) to create a free account on glitch.com to get your webhook's callback URL, but you can skip the WHATSAPP_TOKEN part in the guide - the rest of setting up webhook is the same for WhatsApp and Messenger.
5. Open Messenger's API Settings, as shown in the screenshot below, then in "1. Configure webhooks", set the Callback URL and Verify Token set up in the previous step, and subscribe all message related fields for "Webhook Fields". Finally, in "2. Generate access tokens", connect your Facebook page (see step 1) and copy your page access token for later use.
![](../../../../docs/images/messenger_api_settings.png)
## Writing Llama 3 Enabled Web App
The Python-based web app we developed uses [LangChain](https://www.langchain.com/), an open source LLM development framework, and [Replicate](https://replicate.com/), a service provider hosting LLM models in the cloud, to receive the user query sent by the webhook, which will be covered in the next section, pass the query to Llama 3, and send the Llama 3 answer back to the webhook. For more information on how to use LangChain or LlamaIndex, another LLM app building framework, and other Llama 3 cloud providers or on-premise deployment options to develop Llama 3 apps, see the recipes.
First, let's create a new conda (or you can use venv if you like) environment and install all the required packages:
```
conda create -n messenger-llama python=3.8
conda activate messenger-llama
pip install langchain replicate flask requests uvicorn gunicorn
```
Then, create a Python file named [llama_messenger.py](llama_messenger.py) that creates a Llama 3 instance and defines an HTTP method `msgrcvd_page` to:
1. receive the user message forwarded by the webhook;
2. ask Llama 3 for the answer;
3. send the answer back to the sender using the Facebook graph API.
```
import langchain
from langchain.llms import Replicate
from flask import Flask
from flask import request
import os
import requests
import json
os.environ["REPLICATE_API_TOKEN"] = "<your replicate api token"
llama3_8b_chat = "meta/meta-llama-3-8b-instruct"
llm = Replicate(
model=llama3_8b_chat,
model_kwargs={"temperature": 0.0, "top_p": 1, "max_new_tokens":500}
)
app = Flask(__name__)
@app.route('/msgrcvd_page', methods=['POST', 'GET'])
def msgrcvd_page():
message = request.args.get('message')
sender = request.args.get('sender')
recipient = request.args.get('recipient')
answer = llm(message)
url = f"https://graph.facebook.com/v18.0/{recipient}/messages"
params = {
'recipient': '{"id": ' + sender + '}',
'message': json.dumps({'text': answer}),
'messaging_type': 'RESPONSE',
'access_token': '<page_access_token>'
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, params=params, headers=headers)
return message + "<p/>" + answer
```
Replace <page_access_token> with the access token copied in step 5 "Open Messenger's API Settings" of the previous section. Now it's time to modify the webhook to complete the whole app.
## Modifying the Webhook
Open your glitch.com webhook URL created earlier, and change your `app.js` to simply forward the user message and the user and page ids sent by the Messenger Platform to the Llama 3 enabled web app `llama_messenger.py` described in the previous section:
```
"use strict";
// Imports dependencies and set up http server
const request = require("request"),
express = require("express"),
body_parser = require("body-parser"),
axios = require("axios").default,
app = express().use(body_parser.json()); // creates express http server
// Sets server port and logs message on success
app.listen(process.env.PORT || 1337, () => console.log("webhook is listening"));
// Accepts POST requests at /webhook endpoint
app.post("/webhook", (req, res) => {
// Parse the request body from the POST
let body = req.body;
let sender = req.body["entry"][0]["messaging"][0]['sender']['id']
let recipient = req.body["entry"][0]["messaging"][0]['recipient']['id']
let message = req.body["entry"][0]["messaging"][0]['message']['text']
// Check if this is an event from a page subscription
if (body.object === "page") {
// Returns a '200 OK' response to all requests
res.status(200).send("EVENT_RECEIVED");
let url = "http://<web server public IP>:5000/msgrcvd_page?sender=" + sender + "&recipient=" + recipient + "&message=" + encodeURIComponent(message)
console.log(url)
axios.get(url)
.then(response => {
// Handle the response data
console.log(response.data);
})
.catch(error => {
// Handle errors
console.error('Axios error:', error);
});
} else {
// Return a '404 Not Found' if event is not from a page subscription
res.sendStatus(404);
}
});
// Accepts GET requests at the /webhook endpoint. You need this URL to setup webhook initially.
// info on verification request payload: https://developers.facebook.com/docs/graph-api/webhooks/getting-started#verification-requests
app.get("/webhook", (req, res) => {
/**
* UPDATE YOUR VERIFY TOKEN
*This will be the Verify Token value when you set up webhook
**/
const verify_token = process.env.VERIFY_TOKEN;
// Parse params from the webhook verification request
let mode = req.query["hub.mode"];
let token = req.query["hub.verify_token"];
let challenge = req.query["hub.challenge"];
// Check if a token and mode were sent
if (mode && token) {
// Check the mode and token sent are correct
if (mode === "subscribe" && token === verify_token) {
// Respond with 200 OK and challenge token from the request
console.log("WEBHOOK_VERIFIED: " + token);
res.status(200).send(challenge);
} else {
// Responds with '403 Forbidden' if verify tokens do not match
res.sendStatus(403);
}
}
});
```
Remember to change <web server public IP>, which needs to be publicly visible, to the IP of the server where your Llama 3 enabled web app in the previous section runs.
Note: It's possible and even recommended to implement a webhook in Python and call the Llama directly inside the webhook, instead of making an HTTP request, as the JavaScript code above does, to a Python app which calls Llama and sends the answer to Messenger.
## Running the Chatbot
On your web server, run the following command on a Terminal (see [here](https://flask.palletsprojects.com/en/3.0.x/deploying/gunicorn/) for more info on Gunicorn):
```
gunicorn -b 0.0.0.0:5000 llama_messenger:app
```
If you use Amazon EC2 as your web server, make sure you have port 5000 added to your EC2 instance's security group's inbound rules.
Now you can open your Messenger app, select the Facebook page you connected in Messenger's API Settings, enter a message and receive the Llama 3's answer shortly, as shown in the demo video in the beginning of this post.
To debug any possible issues, go to your glitch.com app log and copy the URL generated there when a Messenger message is sent, which looks like this:
```
http://<web server public IP>:5000/msgrcvd_page?sender=<user id>&recipient=<page id>&message=<msg>
```
Then open the URL in a browser to verify your web server can receive the message and the two ids, and generate a Llama answer before sending the answer back to Messenger.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"cells": [
{
"cell_type": "markdown",
"id": "374b67d0-b446-4d6f-8e07-59e97716c55a",
"metadata": {},
"source": [
"# Sales Bot with Llama3 - A Summarization and RAG Use Case"
]
},
{
"cell_type": "markdown",
"id": "add4953d-07c3-4480-ad91-7d0ea9c9fb55",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"In this notebook you'll take an Amazon product reviews dataset from Kaggle and use Llama3 to obtain product review summaries, upsert those summaries in a vector database, then use Retrieval Augmented Generation (RAG) to power a sales chatbot that can make targeted product recommendations.\n",
"\n",
"Let's take a look at the overall workflow:\n",
"1. We start with a dataset that contains over 10,000 reviews across 900 Amazon musical instruments and accessories.\n",
"2. Using Llama2 70B chat (hosted on OctoAI), we generate summaries of product reviews for each product from the 20 most recent reviews. We format the summaries in JSON format.\n",
"3. We then take the summaries and upsert them into a vector database (Weaviate in this case)\n",
"4. We then use this vector database and Llama3 70B instruct (hosted on OctoAI) to build a RAG-based sales chatbot that provides targeted recommendations to the user based on the products that are present in the inventory.\n",
"\n",
"Note: at the time of writing this tutorial, JSON mode formatting isn't supported for Llama 3 on OctoAI via constrained sampling which is why we are falling back onto Llama 2. This tutorial will be updated when the feature becomes available to rely on Llama 3 exclusively.\n",
"\n",
"### OctoAI\n",
"We'll use [OctoAI](https://octo.ai/) to power all of the GenAI model needs of this notebook: LLMs, image gen, image animation.\n",
"* To use OctoAI, you'll need to go to https://octoai.cloud/ and sign in using your Google or GitHub account.\n",
"* Next you'll need to generate an OctoAI API token by following these [instructions](https://octo.ai/docs/getting-started/how-to-create-an-octoai-access-token). Keep the API token in hand, we'll need it further down in this notebook.\n",
"\n",
"In this example we will use the Llama 3 70b instruct model. You can find more on Llama models on the [OctoAI text generation solution page](https://octoai.cloud/text).\n",
"\n",
"At the time of writing this notebook the following Llama models are available on OctoAI:\n",
"* meta-llama-3-8b-instruct\n",
"* meta-llama-3-70b-instruct\n",
"* codellama-7b-instruct\n",
"* codellama-13b-instruct\n",
"* codellama-34b-instruct\n",
"* llama-2-13b-chat\n",
"* llama-2-70b-chat\n",
"* llamaguard-7b\n",
"\n",
"### Weaviate\n",
"We'll use Weaviate Cloud Services (WCS) for our vector database. You can create an account and Weaviate clusters easily at the following link: https://console.weaviate.cloud/.\n",
"You can then create a cluster, from which you can obtain the REST Endpoint URL and the API key to use the cluster endpoint.\n",
"\n",
"### OpenAI\n",
"We'll be using OpenAI for its embedding model to upsert our vectors into the Weaviate vector database. Create an account and obtain an API key here: https://openai.com/api/\n",
"\n",
"### Local Python Notebook\n",
"We highly recommend launching this notebook from a fresh python environment, for instance you can run the following:\n",
"```\n",
"python3 -m venv .venv \n",
"source .venv/bin/activate\n",
"```\n",
"All you need to run this notebook is to install jupyter notebook with `python3 -m pip install notebook` then run `jupyter notebook` ([link](https://jupyter.org/install)) in the same directory as this `.ipynb` file.\n",
"You don't need to install additional pip packages ahead of running the notebook, since those will be installed right at the beginning. You will need to ensure your system has `imagemagick` installed by following the [instructions](https://imagemagick.org/script/download.php)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "133c2ea4-0256-49cf-9f5a-a9e5bb0bb63f",
"metadata": {},
"outputs": [],
"source": [
"# Let's start by installing the appropriate python packages\n",
"! pip install octoai===1.0.2 openai weaviate-client pandas gradio pydantic"
]
},
{
"cell_type": "markdown",
"id": "75341227-43f8-4a68-b3cb-31e8216f874e",
"metadata": {},
"source": [
"## Part 1: Review Summarization"
]
},
{
"cell_type": "markdown",
"id": "793c06d7-fa67-4c67-a380-081ed3a7a7bf",
"metadata": {},
"source": [
"Let's start by importing all of the packages we need for this example"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "edd366c8-4f0b-4211-83d3-c16e88cbd5c8",
"metadata": {},
"outputs": [],
"source": [
"import gradio\n",
"import json\n",
"import langchain\n",
"import os\n",
"import openai\n",
"import weaviate\n",
"from getpass import getpass\n",
"from json import loads\n",
"from pandas import DataFrame, concat, read_csv\n",
"from pydantic import BaseModel, Field\n",
"from typing import List\n",
"import weaviate.classes as wvc"
]
},
{
"cell_type": "markdown",
"id": "cd171a7c-c5e7-46d5-8a04-a0f7863609be",
"metadata": {},
"source": [
"Enter your OctoAI, Weaviate, and OpenAI tokens below"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3af09686-a654-45b0-98c5-dee6f30440c7",
"metadata": {},
"outputs": [],
"source": [
"# Get OctoAI API token for Llama 2 & 3\n",
"OCTOAI_API_TOKEN = getpass()\n",
"os.environ[\"OCTOAI_API_TOKEN\"] = OCTOAI_API_TOKEN"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "31c3e684-6e5e-41ad-81d4-970b06522553",
"metadata": {},
"outputs": [],
"source": [
"# Get WCS API key\n",
"WCS_API_KEY = getpass()\n",
"os.environ[\"WCS_API_KEY\"] = WCS_API_KEY"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a44f7b71-c4f9-4fd6-9a3b-1322c2fd0c35",
"metadata": {},
"outputs": [],
"source": [
"# Get WCS URL\n",
"WCS_URL = getpass()\n",
"os.environ[\"WCS_URL\"] = WCS_URL"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e4502dfa-c369-4085-a697-fdcda00f970b",
"metadata": {},
"outputs": [],
"source": [
"# Get OpenAI API key for the embedding model\n",
"OPENAI_API_KEY = getpass()\n",
"os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "883986ad-9f60-44d8-ab64-3f566261e055",
"metadata": {},
"outputs": [],
"source": [
"# First let's load the dataset from Kaggle: https://www.kaggle.com/datasets/eswarchandt/amazon-music-reviews\n",
"df = read_csv('Musical_instruments_reviews.csv')"
]
},
{
"cell_type": "markdown",
"id": "c05865a7-307a-425e-a6ee-f057d63db77b",
"metadata": {},
"source": [
"Set `product_record_limit` to a lower number if you just want to do a test run"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "22f024e7-3976-425f-b684-8b2c2c1ed191",
"metadata": {},
"outputs": [],
"source": [
"# Set a product record limit\n",
"product_record_limit = 900"
]
},
{
"cell_type": "markdown",
"id": "06554f51-5983-42fc-8a8e-684ae82099db",
"metadata": {
"scrolled": true
},
"source": [
"# List all of the unique ASIN:\n",
"asin_list = df.asin.unique()\n",
"print(\"There are {} unique products in the music product inventory\".format(len(asin_list)))"
]
},
{
"cell_type": "markdown",
"id": "4941baa1-107b-4f39-8d04-1daa5acd465b",
"metadata": {},
"source": [
"For each one of the unique products, let's group the reviews together and sort them by how recent they are"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "38147b91-2425-46a7-b6c0-221173d81024",
"metadata": {},
"outputs": [],
"source": [
"# Get the reviews for the product ASIN, sorted by recency and store in dict\n",
"review_dict = {}\n",
"for asin in asin_list[0:product_record_limit]:\n",
" reviews = df.loc[df['asin'] == asin]\\\n",
" .sort_values([\"unixReviewTime\"], axis=0, ascending=False)\\\n",
" .reviewText.tolist()\n",
" review_dict[asin] = reviews"
]
},
{
"cell_type": "markdown",
"id": "7d5fb78d-808a-4753-abba-4a3066d76ba7",
"metadata": {},
"source": [
"To be able to store our summaries into our vector DB, we need to have the fields formatted into a JSON object. We use Pydantic base class model here to define our formatting."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b786cde1-116a-47eb-8478-3fa2285dcf9d",
"metadata": {},
"outputs": [],
"source": [
"# Define the Pydantic model that specifies how our output should be formatted\n",
"class ProductRecord(BaseModel):\n",
" \"\"\"The record of a given product\"\"\"\n",
" description: str = Field(description=\"Description of the product\")\n",
" name: str = Field(description=\"Name of the product\")\n",
" review_summary: str = Field(description=\"Summary of all of the reviews\")\n",
" ASIN: str = Field(description=\"ASIN of the product\")\n",
" features: str = Field(description=\"Features of the product based on the reviews\")"
]
},
{
"cell_type": "markdown",
"id": "08226a6e-f994-454b-9a1d-6246b34bfca2",
"metadata": {},
"source": [
"We define our prompt template below."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1cc3fe69-bf0c-4a50-8d9c-1ae6cb99a9ca",
"metadata": {},
"outputs": [],
"source": [
"# Prepare a prompt template\n",
"template = '''\n",
"Here are product reviews for a music product with an ID of {asin}.\n",
" - Respond back only as only JSON!\n",
" - Provide:\n",
" - the product \"description\",\n",
" - the product \"name\",\n",
" - a summary of all the reviews as \"review_summary\",\n",
" - the \"ASIN\" and\n",
" - and the product \"features\" based on the content of these reviews. \n",
" - The \"features\" should be a string describing the features and NOT JSON. \n",
" - Do not include the ASIN in the description field.\n",
" \n",
"The reviews for the product are: {reviews}\n",
"'''"
]
},
{
"cell_type": "markdown",
"id": "9b8dc3fa-4ad9-4329-96a0-353b05a1c43e",
"metadata": {},
"source": [
"We initialize the OctoAI client using OpenAI's API. All we have to do is override the `base_url` and `api_key`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "57c2ff0a-8029-41a6-a06f-41e560b92230",
"metadata": {},
"outputs": [],
"source": [
"# Init OctoAI client\n",
"client = openai.OpenAI(\n",
" base_url=\"https://text.octoai.run/v1\",\n",
" api_key=os.environ[\"OCTOAI_API_TOKEN\"]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "bd0eb425-ceea-4258-a52d-814b7335febb",
"metadata": {},
"source": [
"Iterate over all product ASINs and summarize the top 20 most recent reviews. Note: this takes a while to run unless we parallelize it."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a55839e-a824-4919-b755-730eaac48d83",
"metadata": {},
"outputs": [],
"source": [
"# Produce the 900 product summaries\n",
"review_summaries = []\n",
"counter = 0\n",
"\n",
"# This can take a while to process serially (30min+)\n",
"# TODO: Optimize to run in a few parallel threads to run faster while meeting the 240RPM limit\n",
"for asin, review_list in review_dict.items():\n",
" print(f'Getting review summary {counter} of {len(review_dict)}, ASIN: {asin}')\n",
" try:\n",
" response = client.chat.completions.create(\n",
" model=\"llama-2-70b-chat\",\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
" {\"role\": \"user\", \"content\": template.format(\n",
" asin = asin,\n",
" reviews = review_list[0:20]\n",
" )},\n",
" ],\n",
" temperature=0,\n",
" response_format={\"type\": \"json_object\", \"schema\": ProductRecord.model_json_schema()},\n",
" max_tokens=1024\n",
" )\n",
" print(\"\\n{}\\n\".format(response.choices[0].message.content))\n",
" summary = loads(response.choices[0].message.content)\n",
" summary[\"ASIN\"] = asin\n",
" review_summaries.append(summary)\n",
" except:\n",
" print(f'Issue with ASIN {asin}, skipping')\n",
" pass\n",
" counter += 1\n",
"\n",
"review_summaries = DataFrame(review_summaries)\n",
"\n",
"print(review_summaries)"
]
},
{
"cell_type": "markdown",
"id": "4772d1c1-c9c4-466e-9c80-259804a4286b",
"metadata": {},
"source": [
"# Part 2: Retrieval Augmented Generation"
]
},
{
"cell_type": "markdown",
"id": "ccd97408-d47f-46f3-b601-f66f8a3b20ff",
"metadata": {},
"source": [
"For our RAG use case we're going to rely on Weaviate vector database and on an OpenAI embedding model. \n",
"\n",
"When you define your collection, you'll need to provide properties, i.e. object attributes that you want to store in the collection. These properties map 1:1 to the JSON dictionary keys defined earlier for the `ProductRecord` Pydantic base model."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5dad98ec-531d-4fc2-aed9-9f337b957feb",
"metadata": {},
"outputs": [],
"source": [
"# Connect to WCS\n",
"wcs_client = weaviate.connect_to_wcs(\n",
" cluster_url=os.getenv(\"WCS_URL\"),\n",
" auth_credentials=weaviate.auth.AuthApiKey(os.getenv(\"WCS_API_KEY\")),\n",
" headers={\n",
" \"X-OpenAI-Api-Key\": os.environ[\"OPENAI_API_KEY\"]\n",
" }\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "02953f7b-0149-4c13-a7cc-c4dd1da45d43",
"metadata": {},
"outputs": [],
"source": [
"# Create the collection if it doesn't already exist\n",
"try:\n",
" collection = wcs_client.collections.get(\"Products\")\n",
"except:\n",
" # Create the collection for products\n",
" collection = wcs_client.collections.create(\n",
" name=\"Products\",\n",
" vectorizer_config=wvc.config.Configure.Vectorizer.text2vec_openai(),\n",
" properties=[\n",
" wvc.config.Property(\n",
" name=\"ASIN\",\n",
" data_type=wvc.config.DataType.TEXT\n",
" ),\n",
" wvc.config.Property(\n",
" name=\"name\",\n",
" data_type=wvc.config.DataType.TEXT\n",
" ),\n",
" wvc.config.Property(\n",
" name=\"review_summary\",\n",
" data_type=wvc.config.DataType.TEXT\n",
" ),\n",
" wvc.config.Property(\n",
" name=\"features\",\n",
" data_type=wvc.config.DataType.TEXT\n",
" ),\n",
" wvc.config.Property(\n",
" name=\"description\",\n",
" data_type=wvc.config.DataType.TEXT\n",
" ),\n",
" ]\n",
" )\n",
" print(\"Collection Created!\")"
]
},
{
"cell_type": "markdown",
"id": "1551fd74-b143-4c02-9b56-364d33683fd3",
"metadata": {},
"source": [
"Now we upsert all of the vectors into the databse using OpenAI's embedding model."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "53f779e7-b875-4a19-9f9c-74b45992608e",
"metadata": {},
"outputs": [],
"source": [
"# Convert df to JSON string and then to a list of dictionaries\n",
"data = review_summaries.to_json(orient='records')\n",
"data_list = json.loads(data)\n",
"\n",
"items_to_insert = []\n",
"\n",
"for d in data_list:\n",
" new_item = {\n",
" \"ASIN\": d[\"ASIN\"],\n",
" \"name\": d[\"name\"],\n",
" \"description\": d[\"description\"], \\\n",
" \"features\": d[\"features\"],\n",
" \"review_summary\": d[\"review_summary\"]\n",
" }\n",
" items_to_insert.append(new_item)\n",
"\n",
" # Insert every 100 items\n",
" if len(items_to_insert) == 100:\n",
" collection.data.insert_many(items_to_insert)\n",
" items_to_insert.clear()\n",
"\n",
"# Insert remaining items\n",
"if len(items_to_insert) > 0:\n",
" collection.data.insert_many(items_to_insert)"
]
},
{
"cell_type": "markdown",
"id": "35079318-41a5-46fc-8475-5d728550fb88",
"metadata": {},
"source": [
"Let's now try to run a hybrid search on the following query below.\n",
"Hybrid search combines the results of a vector search and a keyword (BM25F) search by fusing the two result sets.\n",
"It will return the 3 closest entries in the database according to the search criteria."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f707954-c36b-4a83-874b-f817bd33c39a",
"metadata": {},
"outputs": [],
"source": [
"# Hybrid search\n",
"response = collection.query.hybrid(\n",
" query=\"easy to learn instrument\",\n",
" limit=3\n",
")\n",
"for o in response.objects:\n",
" print(o.properties)"
]
},
{
"cell_type": "markdown",
"id": "04d39507-5e8e-4374-a33c-53e57db6ef99",
"metadata": {},
"source": [
"Let's now define a helper function that gives us the relevant context given a string query. Let's see what it returns based on the question: \"What is a good beginner harmonica\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a1ca51c7-83e5-4896-acc9-753060592ba0",
"metadata": {},
"outputs": [],
"source": [
"# Helper function to run hybrid search on a user query and return the closest\n",
"# product review summaries relevant to the user query\n",
"def get_context(question, limit=3):\n",
" response = collection.query.hybrid(\n",
" query=question,\n",
" limit=limit\n",
" )\n",
" return \"\\n\".join([str(o.properties) for o in response.objects])\n",
"\n",
"print(get_context(\"What is a good beginner harmonica\"))"
]
},
{
"cell_type": "markdown",
"id": "677f534c-8be4-4b6b-82d9-2df8e2ad12d4",
"metadata": {},
"source": [
"Great, we're now ready to build a sales assistant helper function.\n",
"\n",
"We first define a prompt template for Llama 3 - based on the context provided by the vector hybrid search (i.e. collection of product summaries of relevance to the question), provide a helpful recommendation to the customer. \n",
"\n",
"Also provide links to the product that the user can click on to view the product on Amazon's website. For that we use the fact that any product referenced by its aSIN can be accessed at the following url: `https://www.amazon.com/exec/obidos/ASIN/<insert aSIN here>`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "856d021a-add5-48f4-a09c-258d2a617095",
"metadata": {},
"outputs": [],
"source": [
"sales_template = \"\"\"\n",
"You are a sales assistant. Answer the user questions as helpfully as possible.\n",
"Only recommend the products that are provided in the context provided below.\n",
"\n",
"Provide a reference to each product you mention with hyperlinks:\n",
"* Provide the name of the product\n",
"* Embed the hyperlink in the name of the product as follows\n",
" * If the product name is \"Solid Electric Guitar Case with Accessories Compartment\"\n",
" * And the aSIN is \"B001EL6I8W\"\n",
" * Format the reference as follows: \n",
" [Solid Electric Guitar Case with Accessories Compartment](https://www.amazon.com/exec/obidos/ASIN/B001EL6I8W)\n",
"\n",
"Finish with a references section.\n",
"\n",
"Customer question: {}\n",
"\n",
"Product context: {}\n",
"\n",
"AI:\n",
"\"\"\"\n",
"\n",
"def sales_assistant(question): \n",
" response = client.chat.completions.create(\n",
" model=\"meta-llama-3-70b-instruct\",\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
" {\"role\": \"user\", \"content\": sales_template.format(question, get_context(question, limit=10))},\n",
" ],\n",
" temperature=0,\n",
" max_tokens=1024\n",
" )\n",
" \n",
" return response.choices[0].message.content\n",
"\n",
"print(sales_assistant(\"what is must have accessory for my new electric guitar\"))"
]
},
{
"cell_type": "markdown",
"id": "faccba14-9216-4420-b6c5-ddf4029d7904",
"metadata": {},
"source": [
"# Part 3: Gradio-based sales assistant demo"
]
},
{
"cell_type": "markdown",
"id": "3e2b73b5-6bdf-4c87-b044-2690fd52605f",
"metadata": {},
"source": [
"In this section we build a simple an interactive sales bot assistant using Gradio."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "53805acb-3e8d-40fa-8045-c589cb14eadd",
"metadata": {},
"outputs": [],
"source": [
"import gradio as gr\n",
"\n",
"def predict(message, history):\n",
" history_openai_format = []\n",
" for human, assistant in history:\n",
" history_openai_format.append({\"role\": \"user\", \"content\": human})\n",
" history_openai_format.append({\"role\": \"assistant\", \"content\": assistant})\n",
" history_openai_format.append({\"role\": \"user\", \"content\": sales_template.format(message, get_context(message, limit=5))})\n",
"\n",
" response = client.chat.completions.create(\n",
" model = 'meta-llama-3-70b-instruct',\n",
" messages = history_openai_format,\n",
" temperature = 0.0,\n",
" stream = True\n",
" )\n",
"\n",
" partial_message = \"\"\n",
" for chunk in response:\n",
" if chunk.choices[0].delta.content is not None:\n",
" partial_message = partial_message + chunk.choices[0].delta.content\n",
" yield partial_message\n",
"\n",
"gr.ChatInterface(predict).launch()"
]
},
{
"cell_type": "markdown",
"id": "6d4e65fe-0246-40b7-adb6-9091cccbc486",
"metadata": {},
"source": [
"**Authors**\n",
"- Thierry Moreau, OctoAI - tmoreau@octo.ai\n",
"- Jonathan Tuite, Weaviate - jon@weaviate.io"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
# Copyright (c) Meta Platforms, Inc. and affiliates.
# This software may be used and distributed according to the terms of the Llama 3 Community License Agreement.
import langchain
from langchain.llms import Replicate
from flask import Flask
from flask import request
import os
import requests
import json
class WhatsAppClient:
API_URL = "https://graph.facebook.com/v17.0/"
WHATSAPP_API_TOKEN = "<Temporary access token from your WhatsApp API Setup>"
WHATSAPP_CLOUD_NUMBER_ID = "<Phone number ID from your WhatsApp API Setup>"
def __init__(self):
self.headers = {
"Authorization": f"Bearer {self.WHATSAPP_API_TOKEN}",
"Content-Type": "application/json",
}
self.API_URL = self.API_URL + self.WHATSAPP_CLOUD_NUMBER_ID
def send_text_message(self,message, phone_number):
payload = {
"messaging_product": 'whatsapp',
"to": phone_number,
"type": "text",
"text": {
"preview_url": False,
"body": message
}
}
response = requests.post(f"{self.API_URL}/messages", json=payload,headers=self.headers)
print(response.status_code)
assert response.status_code == 200, "Error sending message"
return response.status_code
os.environ["REPLICATE_API_TOKEN"] = "<your replicate api token>"
llama3_8b_chat = "meta/meta-llama-3-8b-instruct"
llm = Replicate(
model=llama3_8b_chat,
model_kwargs={"temperature": 0.0, "top_p": 1, "max_new_tokens":500}
)
client = WhatsAppClient()
app = Flask(__name__)
@app.route("/")
def hello_llama():
return "<p>Hello Llama 3</p>"
@app.route('/msgrcvd', methods=['POST', 'GET'])
def msgrcvd():
message = request.args.get('message')
answer = llm(message)
print(message)
print(answer)
client.send_text_message(llm(message), "<your phone number>")
return message + "<p/>" + answer
# Building a Llama 3 Enabled WhatsApp Chatbot
This step-by-step tutorial shows the complete process of building a Llama 3 enabled WhatsApp chatbot. A demo video of using the iOS WhatsApp to send a question to a test phone number and receive the Llama 3 generated answer is [here](https://drive.google.com/file/d/1fZDaOsvyE1yrNGETV-e0SvL14BYeAI6R/view).
If you're interested in a Llama 3 enabled Messenger chatbot, see [here](../messenger_llama/messenger_llama3.md) for a tutorial.
## Overview
Businesses of all sizes can use the [WhatsApp Business API](https://developers.facebook.com/docs/whatsapp/cloud-api/overview) to connect their customers with human agents or Llama 3 powered chatbots. The benefits of an intelligent and knowledgable chatbot are obvious, including cost saving and better customer experience such as 24x7 availability. In this blog, we'll cover the details of integrating Llama 3 with the WhatsApp Business API to build a basic Llama 3 enabled chatbot.
The diagram below shows the components and overall data flow of the Llama 3 enabled WhatsApp chatbot demo we built, using Amazon EC2 instance as an example for running the web server.
![](../../../../docs/images/whatsapp_llama_arch.jpg)
## Getting Started with WhatsApp Business Cloud API
First, open the [WhatsApp Business Platform Cloud API Get Started Guide](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started#set-up-developer-assets) and follow the first four steps to:
1. Add the WhatsApp product to your business app;
2. Add a recipient number;
3. Send a test message;
4. Configure a webhook to receive real time HTTP notifications.
For the last step, you need to further follow the [Sample Callback URL for Webhooks Testing Guide](https://developers.facebook.com/docs/whatsapp/sample-app-endpoints) to create a free account on glitch.com to get your webhook's callback URL.
Now open the [Meta for Develops Apps](https://developers.facebook.com/apps/) page and select the WhatsApp business app and you should be able to copy the curl command (as shown in the App Dashboard - WhatsApp - API Setup - Step 2 below) and run the command on a Terminal to send a test message to your WhatsApp.
![](../../../../docs/images/whatsapp_dashboard.jpg)
Note down the "Temporary access token", "Phone number ID", and "a recipient phone number" in the API Setup page above, which will be used later.
## Writing Llama 3 Enabled Web App
The Python-based web app we developed uses [LangChain](https://www.langchain.com/), an open source LLM development framework, and [Replicate](https://replicate.com/), a service provider hosting LLM models in the cloud, to receive the user query sent by the webhook, which will be covered in the next section, pass the query to Llama 3, and send the Llama 3 answer back to the webhook. For more information on how to use LangChain and Replicate to develop Llama 3 apps, see the recipes - you may also replace Replicate with other Llama deployment options shown in the demo apps.
First, let's create a new conda (or you can use venv if you like) environment and install all the required packages:
```
conda create -n whatsapp-llama python=3.8
conda activate whatsapp-llama
pip install langchain replicate flask requests uvicorn gunicorn
```
Then, create a Python file named llama_chatbot.py with the following code, which defines a class `WhatsAppClient` and a method `send_text_message` to post a message (the answer generated by Llama 3 on a user query) to the WhatsApp Cloud API, which then sends the answer back to the WhatsApp user. Remember to set `WHATSAPP_API_TOKEN` and `WHATSAPP_CLOUD_NUMBER_ID` to the values you saved in the previous section.
```
import langchain
from langchain.llms import Replicate
from flask import Flask
from flask import request
import os
import requests
import json
class WhatsAppClient:
API_URL = "https://graph.facebook.com/v17.0/"
WHATSAPP_API_TOKEN = "<Temporary access token from your WhatsApp API Setup>"
WHATSAPP_CLOUD_NUMBER_ID = "<Phone number ID from your WhatsApp API Setup>"
def __init__(self):
self.headers = {
"Authorization": f"Bearer {self.WHATSAPP_API_TOKEN}",
"Content-Type": "application/json",
}
self.API_URL = self.API_URL + self.WHATSAPP_CLOUD_NUMBER_ID
def send_text_message(self, message, phone_number):
payload = {
"messaging_product": 'whatsapp',
"to": phone_number,
"type": "text",
"text": {
"preview_url": False,
"body": message
}
}
response = requests.post(f"{self.API_URL}/messages", json=payload, headers=self.headers)
return response.status_code
```
Finally, add the code below to llama_chatbot.py, which creates a Llama 3 instance and defines an HTTP method `msgrcvd` to:
1. receive the user message forwarded by the webhook;
2. ask Llama 3 for the answer;
3. call the `WhatsAppClient`'s `send_text_message`` with a recipient's phone number.
```
os.environ["REPLICATE_API_TOKEN"] = "<your replicate api token>"
llama3_8b_chat = "meta/meta-llama-3-8b-instruct"
llm = Replicate(
model=llama3_8b_chat,
model_kwargs={"temperature": 0.0, "top_p": 1, "max_new_tokens":500}
)
client = WhatsAppClient()
app = Flask(__name__)
@app.route("/")
def hello_llama():
return "<p>Hello Llama 3</p>"
@app.route('/msgrcvd', methods=['POST', 'GET'])
def msgrcvd():
message = request.args.get('message')
answer = llm(message)
client.send_text_message(answer, "<a recipient phone number from your WhatsApp API Setup>")
return message + "<p/>" + answer
```
The complete script of llama_chatbot.py is [here](llama_chatbot.py).
Now it's time to modify the webhook to complete the whole app.
## Modifying the Webhook
Open your glitch.com webhook URL created earlier, and after the code snippet in app.js:
```
// message received!
console.log(req.body["entry"][0]["changes"][0]["value"]["messages"][0]["text"]["body"]);
```
add the code below - remember to change <web server public IP>, which needs to be publicly visible, to the IP of the server where your Llama 3 enabled web app in the previous section runs:
```
let url = "http://<web server public IP>:5000/msgrcvd?message=" +
req.body["entry"][0]["changes"][0]["value"]["messages"][0]["text"]["body"]
axios.get(url)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Axios error:', error);
});
```
The code simply forwards the user message received by the WhatsApp Cloud Platform to the Llama 3 enabled web app llama_chatbot.py described in the previous section. Because the functionality of calling the WhatsApp Cloud API to send a message has been implemented in the `send_text_message` in Python above, you can comment out the whole following code snippet in the original app.js:
```
'// info on WhatsApp text message payload: https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples#text-messages
if (req.body.object) {
...
}
```
Note: It's possible and even recommended to implement a webhook in Python and call Llama 3 directly inside the webhook, instead of making an HTTP request, as the JavaScript code above does, to a Python app which calls Llama 3 and sends the answer to WhatsApp.
## Running the Chatbot
On your web server, run the following command on a Terminal:
```
gunicorn -b 0.0.0.0:5000 llama_chatbot:app
```
If you use Amazon EC2 as your web server, make sure you have port 5000 added to your EC2 instance's security group's inbound rules. Write down your web server's public IP, update the URL below with it, then open the URL in a browser to verify you can see the answer sent to your WhatsApp app, as well as shown in the browser:
```
http://<web server public IP>:5000/msgrcvd?message=who%20wrote%20the%20book%20godfather
```
Now you can open your WhatsApp app, enter a question and receive the Llama 3's answer shortly, as shown in the demo video in the beginning of this post.
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment