Step by step guide to create personalized AI with ChatGPT by using LangChain
Tags: ai, chatgpt, langchain, tutorial
Published: 2024-03-12 18:41:48

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p04ubvys79lxygvx2h28.png)
<p>As an AI language model, ChatGPT is capable of performing a variety of tasks like language translation, writing songs, answering research questions, and even generating computer code. With its impressive abilities, ChatGPT has quickly become a popular tool for various applications, from chatbots to content creation.<br>But despite its advanced capabilities, ChatGPT is not able to access your personal data. So in this article, I will demonstrate below steps to build custom ChatGPT AI by using <a href="https://python.langchain.com/docs/get_started/introduction.html" rel="nofollow"><strong>LangChain Framework</strong></a>:<!--break--></p>
<ul>
<li>
<h3>Step 1: Load the document&nbsp;</h3></li>
<li>
<h3>Step 2: Splitting the document into chunks</h3></li>
<li>
<h3>Step 3: Use Embedding against Chunks Data and convert to vectors</h3></li>
<li>
<h3>Step 4: Save data to the Vector database</h3></li>
<li>
<h3>Step 5: Take&nbsp;data (question) from the user and get&nbsp;the&nbsp;embedding</h3></li>
<li>
<h3>Step 6: Connect to VectorDB and do a semantic search</h3></li>
<li>
<h3>Step 7: Retrieve relevant responses based on user queries and send them to LLM(ChatGPT)</h3></li>
<li>
<h3>Step 8: Get an answer from LLM and send it back to the user</h3></li>
</ul>
<p>&nbsp; NOTE: Please read my previous article <a href="https://community.intersystems.com/post/langchain-%E2%80%93-unleashing-full-potential-llms" rel="nofollow"><strong>LangChain – Unleashing the full potential of LLMs</strong></a> to get more details about LangChain and about how to get OpenAI API Key</p>
<p>&nbsp;</p>
<p>So, let's begin<br>&nbsp; &nbsp; &nbsp;</p>
<h3>Step1: Load the document&nbsp;</h3>
<p>First of all, we need to load the document. So we will import PyPDFLoader for PDF document&nbsp;</p>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">ClassMethod SavePDF(filePath) [ Language = python ]
{
<span class="hljs-comment">#for PDF file we need to import PyPDFLoader from langchain framework</span>
<span class="hljs-keyword">from</span> langchain.document_loaders <span class="hljs-keyword">import</span> PyPDFLoader
<span class="hljs-comment"># for CSV file we need to import csv_loader</span>
<span class="hljs-comment"># for Doc we need to import UnstructuredWordDocumentLoader</span>
<span class="hljs-comment"># for Text document we need to import TextLoader</span>
<span class="hljs-comment">#import os to set environment variable</span>
<span class="hljs-keyword">import</span> os
<span class="hljs-comment">#Assign OpenAI API Key to environment variable </span>
os.environ[<span class="hljs-string">'OPENAI_API_KEY'</span>] = <span class="hljs-string">"apiKey"</span>
<span class="hljs-comment">#Init loader</span>
loader = PyPDFLoader(filePath) &nbsp; 
<span class="hljs-comment">#Load document </span>
documents = loader.load()
<span class="hljs-keyword">return</span> documents
}</code></pre>
<p><!--break--></p>
<h3>Step 2: Splitting the document into chunks</h3>
<p>Language Models are often limited by the amount of text that you can pass to them. Therefore, it is necessary to split them up into smaller chunks. LangChain provides several utilities for doing so.</p>
<p>Using a Text Splitter can also help improve the results from vector store searches, as eg. smaller chunks may sometimes be more likely to match a query. Testing different chunk sizes (and chunk overlap) is a worthwhile exercise to tailor the results to your use case.</p>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">ClassMethod splitText(documents) [ Language = python ]
{
<span class="hljs-comment">#In order to split the document we need to import RecursiveCharacterTextSplitter from Langchain framework  </span>
<span class="hljs-keyword">from</span> langchain.text_splitter <span class="hljs-keyword">import</span> RecursiveCharacterTextSplitter
<span class="hljs-comment">#Init text splitter, define chunk size 1000 and overlap = 0</span>
text_splitter = RecursiveCharacterTextSplitter(chunk_size=<span class="hljs-number">1000</span>, chunk_overlap=<span class="hljs-number">0</span>)
<span class="hljs-comment">#Split document into chunks</span>
texts = text_splitter.split_documents(documents)
<span class="hljs-keyword">return</span> texts
}</code></pre>
<p><!--break--></p>
<h3>Step 3: Use Embedding against Chunks Data and convert to vectors</h3>
<p><span style="color:#c0392b;"><strong>Text embeddings are the heart and soul of Large Language Operations</strong></span>. Technically, we can work with language models with natural language but storing and retrieving natural language is highly inefficient.&nbsp;</p>
<p>To make it more efficient, we need to transform text data into vector forms. There are dedicated ML models for creating embeddings from texts. The texts are converted into multidimensional vectors. Once embedded, we can group, sort, search, and more over these data. We can calculate the distance between two sentences to know how closely they are related. And the best part of it is these operations are not just limited to keywords like the traditional database searches but rather capture the semantic closeness of two sentences. This makes it a lot more powerful, thanks to Machine Learning.<br>&nbsp;</p>
<p><strong>Text embedding models</strong>&nbsp;take text input and return a list of floats (embeddings), which are the numerical representation of the input text. Embeddings help extract information from a text. This information can then be later used, e.g., for calculating similarities between texts (e.g., movie summaries).</p>
<p><img alt="Text embedding models take a text as an input and output its numerical representation as a list of floats" src="https://miro.medium.com/v2/resize:fit:700/1*m-B8T61sERyREFwx56y3EQ.png"></p>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">    ClassMethod getEmbeddings(query) [ Language = python ]
    {
    <span class="hljs-comment">#Get embeddings model from Langchain framework</span>
    <span class="hljs-keyword">from</span> langchain.embeddings <span class="hljs-keyword">import</span> OpenAIEmbeddings
    <span class="hljs-comment">#Define embedding</span>
    embedding = OpenAIEmbeddings()
    <span class="hljs-keyword">return</span> embedding
    }
    </code></pre>
<p><!--break--></p>
<h3>Step 4: Save data to the Vector database</h3>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">    ClassMethod saveDB(texts,embedding) [ Language = python ]
    {
    <span class="hljs-comment">#Get Chroma db  from langchain</span>
    <span class="hljs-keyword">from</span> langchain.vectorstores <span class="hljs-keyword">import</span> Chroma&nbsp; &nbsp; &nbsp;&nbsp;
    <span class="hljs-comment"># Embed and store the texts</span>
    <span class="hljs-comment"># Supplying a persist_directory will store the embeddings on disk</span>
    <span class="hljs-comment"># e.g we are saving data in myData folder in current application path</span>
    persist_directory = <span class="hljs-string">"myData"</span>
    vectordb = Chroma.from_documents(documents=texts, embedding=embedding, persist_directory=persist_directory)
    <span class="hljs-comment">#save document locally</span>
    vectordb.persist()
    vectordb = <span class="hljs-keyword">None</span>
    }
    </code></pre>
<p><!--break--></p>
<h3>Step 5: Take&nbsp;data (question) from the user and get&nbsp;the&nbsp;embedding</h3>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">    ClassMethod getVectorData(query) [ Language = python ]
    {
    <span class="hljs-comment">#NOTE : We should have same embedding used when we saved data</span>
    <span class="hljs-keyword">from</span> langchain.embeddings <span class="hljs-keyword">import</span> OpenAIEmbeddings
    <span class="hljs-comment">#get embeddings</span>
    embedding = OpenAIEmbeddings()
    <span class="hljs-comment">#take user input (parameter)</span>
    query = query
    <span class="hljs-comment">#Code continue...</span>
</code></pre>
<p><!--break--></p>
<h3>Step 6: Connect to VectorDB and do a semantic search</h3>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs"> <span class="hljs-comment">#code continue....     </span>
 <span class="hljs-keyword">from</span> langchain.vectorstores <span class="hljs-keyword">import</span> Chroma
 persist_directory = <span class="hljs-string">"myData"</span>
 <span class="hljs-comment">## Now we can load the persisted database from disk, and use it as normal.&nbsp;</span>
 vectordb = Chroma(persist_directory=persist_directory, embedding_function=embedding)
 <span class="hljs-keyword">return</span> vectordb
 }</code></pre>
<p><!--break--></p>
<h3>Step 7: Retrieve relevant responses based on user queries and send them to LLM(ChatGPT)</h3>
<p><strong><span style="color: rgb(192, 57, 43);">Conversational memory</span></strong> is how a chatbot can respond to multiple queries in a chat-like manner. It enables a coherent conversation, and without it, every query would be treated as an entirely independent input without considering past interactions.</p>
<p>The LLM with and without conversational memory. The blue boxes are user prompts and in grey are the LLMs responses. Without conversational memory (right), the LLM cannot respond using knowledge of previous interactions.</p>
<p>The memory allows a&nbsp;<strong>L</strong>arge&nbsp;<strong>L</strong>anguage&nbsp;<strong>M</strong>odel (LLM) to remember previous interactions with the user. By default, LLMs are&nbsp;<em>stateless</em>&nbsp;— meaning each incoming query is processed independently of other interactions. The only thing that exists for a stateless agent is the current input, nothing else.</p>
<p><br>The&nbsp;<span style="color:#c0392b;"><strong>ConversationalRetrievalChain</strong>&nbsp;</span>is a conversational AI model that is designed to retrieve relevant responses based on user queries. It is a part of the Langchain team's technology. The model uses a retrieval-based approach, where it searches through a database of pre-existing responses to find the most appropriate answer for a given query. The model is trained on a large dataset of conversations to learn patterns and context in order to provide accurate and helpful responses.</p>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">ClassMethod retriveResponse(vectordb) [ Language = python ]
{
<span class="hljs-keyword">from</span> langchain.llms <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">from</span> langchain.memory <span class="hljs-keyword">import</span> ConversationBufferMemory
<span class="hljs-keyword">from</span> langchain.chains <span class="hljs-keyword">import</span> ConversationalRetrievalChain
<span class="hljs-comment">#Conversational memory is how a chatbot can respond to multiple queries</span>
memory = ConversationBufferMemory(memory_key=<span class="hljs-string">"chat_history"</span>, return_messages=<span class="hljs-keyword">True</span>)
<span class="hljs-comment">#The&nbsp;ConversationalRetrievalChain&nbsp;is a conversational AI model that is designed to retrieve relevant responses based on user queries</span>
qa = ConversationalRetrievalChain.from_llm(OpenAI(temperature=<span class="hljs-number">0</span>), vectordb.as_retriever(), memory=memory)
<span class="hljs-keyword">return</span> qa
}</code></pre>
<p><!--break--></p>
<h3><br>Step 8: Get an answer from LLM and send it back to the user<span>&nbsp;</span></h3>
<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs">ClassMethod getAnswer(qa) [ Language = python ]
{
<span class="hljs-comment">#Get an answer from LLM and send it back to the user</span>
getAnswer = qa.run(query)
<span class="hljs-keyword">return</span> getAnswer
}</code></pre>
<p>To check more details and features, please visit my application <a href="https://openexchange.intersystems.com/package/irisChatGPT" rel="nofollow"><strong>irisChatGPT</strong></a>&nbsp;</p>
<p><strong>Related Video</strong></p>
{% embed https://www.youtube.com/watch?v=h9JoqbUKFBk %}
<p>Thanks</p>