{ "cells": [ { "cell_type": "markdown", "id": "f2ca422f1caa894d", "metadata": {}, "source": [ "# Local Chat with Codebase\n", "\n", "In this recipe, we will be using all Open Source Software to build a local ChatBot that has access to some documentation. We will be using Mirascope documentation in this example, but this should work on all types of documents. Also note that we will be using a smaller Llama 3.1 8B so the results will not be as impressive as larger models. Later, we will take a look at how OpenAI's GPT compares with Llama.\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "391703b0", "metadata": {}, "source": [ "## Setup\n", "\n", "To set up our environment, first let's install all of the packages we will use:" ] }, { "cell_type": "code", "execution_count": null, "id": "79ffb0afbd78a71a", "metadata": {}, "outputs": [], "source": [ "!pip install \"mirascope[openai]\"\n", "!pip install llama-index llama-index-llms-ollama llama-index-embeddings-huggingface huggingface" ] }, { "cell_type": "markdown", "id": "a804032d4d19c961", "metadata": {}, "source": [ "## Configuration\n", "\n", "For this setup, we are using [Ollama](https://github.com/ollama/ollama), but vLLM would also work." ] }, { "cell_type": "code", "execution_count": null, "id": "592e677f9b71afca", "metadata": {}, "outputs": [], "source": [ "from llama_index.core import (\n", " Settings,\n", " SimpleDirectoryReader,\n", " VectorStoreIndex,\n", ")\n", "from llama_index.legacy.embeddings import HuggingFaceEmbedding\n", "from llama_index.legacy.llms import Ollama\n", "\n", "Settings.llm = Ollama(model=\"llama3.1\")\n", "Settings.embed_model = HuggingFaceEmbedding(model_name=\"BAAI/bge-small-en-v1.5\")" ] }, { "cell_type": "markdown", "id": "54a6561ff39ca350", "metadata": {}, "source": [ "\n", "We will be using LlamaIndex for RAG, and setting up the proper models we will be using for Re-ranking and the Embedding model.\n", "\n", "## Store Embeddings\n", "\n", "The first step is to grab our docs and embed them into a vectorstore. In this recipe, we will be storing our vectorstore locally, but using Pinecone or other cloud vectorstore providers will also work.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "8e2b78f59c166a58", "metadata": {}, "outputs": [], "source": [ "from llama_index.core.storage import StorageContext\n", "from llama_index.core.vector_stores import SimpleVectorStore\n", "\n", "documents = SimpleDirectoryReader(\"PATH/TO/YOUR/DOCS\").load_data()\n", "vector_store = SimpleVectorStore()\n", "storage_context = StorageContext.from_defaults(vector_store=vector_store)\n", "index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)\n", "index.storage_context.persist()" ] }, { "cell_type": "markdown", "id": "81eb217df593f1c0", "metadata": {}, "source": [ "\n", "## Load Embeddings\n", "\n", "After we saved our embeddings, we can use the below code to retrieve it and load in memory:\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b28e9cdd0178f0a5", "metadata": {}, "outputs": [], "source": [ "from llama_index.core import load_index_from_storage\n", "\n", "storage_context = StorageContext.from_defaults(persist_dir=\"storage\")\n", "loaded_index = load_index_from_storage(storage_context)\n", "query_engine = loaded_index.as_query_engine()" ] }, { "cell_type": "markdown", "id": "a5ae2e44b614cfef", "metadata": {}, "source": [ "\n", "## Code\n", "\n", "We need to update LlamaIndex `default_parse_choice_select_answer_fn` for Llama 3.1. You may need to update the `custom_parse_choice_select_answer_fn` depending on which model you are using. Adding re-ranking is extremely important to get better quality retrievals so the LLM can make better context-aware answers.\n", "\n", "We will be creating an Agent that will read Mirascope documentation called MiraBot which will answer questions regarding Mirascope docs.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "3370e1697feaea48", "metadata": {}, "outputs": [], "source": [ "import re\n", "\n", "from llama_index.core.base.response.schema import Response\n", "from llama_index.core.postprocessor import LLMRerank\n", "from llama_index.core.storage import StorageContext\n", "from llama_index.core.vector_stores import SimpleVectorStore\n", "from llama_index.embeddings.huggingface import HuggingFaceEmbedding\n", "from llama_index.llms.ollama import Ollama\n", "from mirascope.core import openai, prompt_template\n", "from openai import OpenAI\n", "from pydantic import BaseModel\n", "\n", "\n", "def custom_parse_choice_select_answer_fn(\n", " answer: str, num_choices: int, raise_error: bool = False\n", ") -> tuple[list[int], list[float]]:\n", " \"\"\"Custom parse choice select answer function.\"\"\"\n", " answer_lines = answer.split(\"\\n\")\n", " answer_nums = []\n", " answer_relevances = []\n", " for answer_line in answer_lines:\n", " line_tokens = answer_line.split(\",\")\n", " if len(line_tokens) != 2:\n", " if not raise_error:\n", " continue\n", " else:\n", " raise ValueError(\n", " f\"Invalid answer line: {answer_line}. \"\n", " \"Answer line must be of the form: \"\n", " \"answer_num:Check out OpenAI Implementation
\n", "\n", "While we demonstrated an open source version of chatting with our codebase, there are several improvements we can make to get better results. Refer to Documentation Agent Cookbook for a detailed walkthrough on the improvements made.\n", "
\n", "Additional Real-World Applications
\n", "