nadaaaita commited on
Commit
0436f2c
·
1 Parent(s): 06cf053

set up folder structure

Browse files
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .env
2
+ *.pyc
3
+ __pycache__
4
+ notebooks/.ipynb_checkpoints
Pipfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [[source]]
2
+ url = "https://pypi.org/simple"
3
+ verify_ssl = true
4
+ name = "pypi"
5
+
6
+ [packages]
7
+ gradio = "*"
8
+ langchain-openai = "*"
9
+ langchain = "*"
10
+ langchain-qdrant = "*"
11
+ python-dotenv = "*"
12
+ pandas = "*"
13
+ numpy = "*"
14
+ jupyter = "*"
15
+ ipykernel = "*"
16
+ langgraph = "*"
17
+
18
+ [dev-packages]
19
+
20
+ [requires]
21
+ python_version = "3.11"
Pipfile.lock ADDED
The diff for this file is too large to render. See raw diff
 
app.py CHANGED
@@ -1,63 +0,0 @@
1
- import gradio as gr
2
- from huggingface_hub import InferenceClient
3
-
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
-
9
-
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
-
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
-
42
- """
43
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
44
- """
45
- demo = gr.ChatInterface(
46
- respond,
47
- additional_inputs=[
48
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
49
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
50
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
51
- gr.Slider(
52
- minimum=0.1,
53
- maximum=1.0,
54
- value=0.95,
55
- step=0.05,
56
- label="Top-p (nucleus sampling)",
57
- ),
58
- ],
59
- )
60
-
61
-
62
- if __name__ == "__main__":
63
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.py ADDED
File without changes
config/__init__.py ADDED
File without changes
config/settings.py ADDED
File without changes
example_app.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from huggingface_hub import InferenceClient
3
+
4
+ """
5
+ For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
+ """
7
+ client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
+
9
+
10
+ def respond(
11
+ message,
12
+ history: list[tuple[str, str]],
13
+ system_message,
14
+ max_tokens,
15
+ temperature,
16
+ top_p,
17
+ ):
18
+ messages = [{"role": "system", "content": system_message}]
19
+
20
+ for val in history:
21
+ if val[0]:
22
+ messages.append({"role": "user", "content": val[0]})
23
+ if val[1]:
24
+ messages.append({"role": "assistant", "content": val[1]})
25
+
26
+ messages.append({"role": "user", "content": message})
27
+
28
+ response = ""
29
+
30
+ for message in client.chat_completion(
31
+ messages,
32
+ max_tokens=max_tokens,
33
+ stream=True,
34
+ temperature=temperature,
35
+ top_p=top_p,
36
+ ):
37
+ token = message.choices[0].delta.content
38
+
39
+ response += token
40
+ yield response
41
+
42
+ """
43
+ For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
44
+ """
45
+ demo = gr.ChatInterface(
46
+ respond,
47
+ additional_inputs=[
48
+ gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
49
+ gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
50
+ gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
51
+ gr.Slider(
52
+ minimum=0.1,
53
+ maximum=1.0,
54
+ value=0.95,
55
+ step=0.05,
56
+ label="Top-p (nucleus sampling)",
57
+ ),
58
+ ],
59
+ )
60
+
61
+
62
+ if __name__ == "__main__":
63
+ demo.launch()
notebooks/01 Basic Chatbot.ipynb ADDED
@@ -0,0 +1,603 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "name": "stdout",
10
+ "output_type": "stream",
11
+ "text": [
12
+ "langgraph-learning\n"
13
+ ]
14
+ }
15
+ ],
16
+ "source": [
17
+ "from dotenv import load_dotenv\n",
18
+ "from typing import Annotated\n",
19
+ "from typing_extensions import TypedDict\n",
20
+ "from langchain.tools import tool\n",
21
+ "from langchain.schema import Document\n",
22
+ "from langgraph.graph import StateGraph, START, END\n",
23
+ "from langgraph.graph.message import add_messages\n",
24
+ "from langgraph.prebuilt import ToolNode, tools_condition\n",
25
+ "from langgraph.checkpoint.memory import MemorySaver\n",
26
+ "from langchain_openai import ChatOpenAI\n",
27
+ "from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate\n",
28
+ "from langchain.schema import SystemMessage, HumanMessage, AIMessage\n",
29
+ "\n",
30
+ "from IPython.display import Image, display\n",
31
+ "import sys\n",
32
+ "import os\n",
33
+ "\n",
34
+ "load_dotenv('/Users/nadaa/Documents/code/langgraph_learning/.env')\n",
35
+ "print(os.environ['LANGCHAIN_PROJECT'])\n",
36
+ "\n",
37
+ "sys.path.append(os.path.abspath('..'))\n",
38
+ "%load_ext autoreload\n",
39
+ "%autoreload 2\n",
40
+ "\n",
41
+ "import src.qdrant_manager as qm\n",
42
+ "\n",
43
+ "# Check available kernels\n",
44
+ "from jupyter_client import kernelspec\n",
45
+ "print(\"Available kernels:\")\n",
46
+ "for kernel in kernelspec.find_kernel_specs():\n",
47
+ " print(kernel)\n",
48
+ "\n",
49
+ "# If you still can't see your kernel, you might need to restart your Jupyter environment\n",
50
+ "# or ensure that the kernel is properly installed and registered.\n",
51
+ "# You can also try running the following in a terminal:\n",
52
+ "# python -m ipykernel install --user --name=your_kernel_name\n",
53
+ "\n",
54
+ "# If issues persist, check your Jupyter configuration and environment setup.\n",
55
+ "\n",
56
+ "\n"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "markdown",
61
+ "metadata": {},
62
+ "source": [
63
+ "# Build a Basic Chatbot"
64
+ ]
65
+ },
66
+ {
67
+ "cell_type": "code",
68
+ "execution_count": 2,
69
+ "metadata": {},
70
+ "outputs": [
71
+ {
72
+ "data": {
73
+ "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCADqAGsDASIAAhEBAxEB/8QAHQABAAMBAAMBAQAAAAAAAAAAAAUGBwQCAwgBCf/EAE0QAAEDAwEDBQkKDAQHAAAAAAECAwQABREGBxIhExUxQZQIFiJRVmGB0dMUFyMyNlRVcXSVJTVCUlNzkZKTsrO0YnKD0iRDREaxwfD/xAAaAQEBAAMBAQAAAAAAAAAAAAAAAQIDBAUH/8QAMxEAAgECAgcFCAIDAAAAAAAAAAECAxEEMRIUIVFxkaFBUmHB0RMjMjNTYoGSIkLh8PH/2gAMAwEAAhEDEQA/AP6p0pUFdrtLk3AWi0hIlhIXJmODebiIPRw/KcV+SnoABUrhupXnGLm7IuZMvyGozZcecQ0gdKlqCQPSajzqmyg4N3gA/aUeuuBnZ/ZSsPXCKL3MxhUq6gPrPHPAEbqPqQlI81dw0rZQMczwMfZUeqttqKzbY2H731WX6YgdpR66d9Vl+mIHaUeunerZfoeB2ZHqp3q2X6HgdmR6qe58ehdg76rL9MQO0o9dO+qy/TEDtKPXTvVsv0PA7Mj1U71bL9DwOzI9VPc+PQbB31WX6YgdpR66d9Vl+mIHaUeunerZfoeB2ZHqp3q2X6HgdmR6qe58eg2HTDu0G4EiLMjySOpl1K//AAa66gpmhNOTx8NY7epXU4mMhK0+dKgAQfODXG6iZosF9L8m6WMH4Zp9XKPw0/noV8ZxA6SlRUoDJBOAmmhCeyD27n6/8JZPItNK8W3EPNpcbUlaFAKSpJyCD0EGvKuch65D6IzDjzhwhtJWo+IAZNQGz9lR0xFuDwHuy6jnGQoZ4rcAIHH81O4geZAqauUT3fbpUXOOXaW3nxZBH/uorQUr3XouyrIKXERG2nEqGClxA3FpI8ykkeiuhbKLtvXmXsJ6lKVzkK7rraDp/ZrYxd9SXAW6Cp5EZtQaW6466s4Q2222lS1qODhKQTwPirN9Zd1NpnTE7Z+qMzPudp1VIlNmZHtkxbkdDLbpUQyhhS1L5RsIKMBQG8ojCSam+6FtNou2iIgu9q1LcBHuTEmJJ0lHU9cLdIQFFEptKcnweIOEq+PgpIJrIzO2gu6e2P631bp69XiTp7UM8zWods/Ca4LseTHjyXYjeSlZC2ytCRkb2cDiABs+s+6C0Fs9uceBqG+Ltkh6O3K+EgSVNstLJCFvLS2UsgkEZcKeg+KvfqfbnorR+pkaduV3d58ciNTm4EOBJluuMOLWhLiUstr3k5bVkj4uAVYBBOC7cxqvaBcda22XaNev2q56caRpS12Jl6NFdeejr5bnBaSkJWlwpSWn1BO4DhKiTVw2KafuidrsC9TbJcYTHvb2aB7pnQnGdyQl98usEqSMOJ8AqR0jwT1igLhst7oK1bTNbav001BnwplkujsFlbkCUGn222mlKcU6plLbat5xQDZVvEJChkKBrV6w/ZPIuGi9r+0jT1z09eko1BqBV6t94agrcty2FQmEkKkAbqFhTCk7qsEkpxnNbhQClKUBWNDYgtXWyJwGrRMMaOlOcJYU2h1pIz1JS4EDzIqz1WdJJ90XrVM9OeSeuAZbJGMhplttR8/hhweirNXRX+Y3wvxtt6leYqrvBWjblKlhtS7FNcL0jk0lSobxxvOED/lKxlRHxFZUcpUpSLRStcJ6N09qYKrqjZ7ozagxAk6g0/ZtUMsJUqI7OityUoSvG8UFQOArdTnHTgVAjubdlASU+9vpbdJBI5pYwT1fk+c1ZZOgrW4+4/DVLs7zhJWq2SVsJUScklsHcJJ45Kc9PHia9XeTI6tU34f6zPsq2aFJ5StxXpcbDw0hso0Xs/mPy9M6Us9glPt8k69bYTbC1ozndJSBkZAOKtdVfvJkeVV+/jM+yp3kyPKq/fxmfZU9nT7/AEYst5aKVlmsbddbHqbQsCLqm8GPebu7Cl8q6zvcmmBLfG58GPC32G/Hw3uHWLX3kyPKq/fxmfZU9nT7/Riy3kvqDTtr1XZ5NpvVujXW2SQA9DmNJdacAIUApKgQcEA/WBVJR3N2ylsko2caXSSCMi0sDgRgj4viNT/eTI8qr9/GZ9lTvJkeVV+/jM+yp7On3+jFlvIm0bAdmlgukW5W3QOnIFwiuJeYlRrYyhxpYOQpKgnIIPWKnrtf3JMly02Rbci653XXfjNQUnpW7/ix8VvpUcdCd5Sec6CZkcJt5vU9s8C05OU0lX18luZHm6D11PW62RLRERFhRmokdOSG2UBIyek8Os9Z66e7htT0n0GxHhZrTHsVqi2+KFBiOgISVneUrxqUetROST1kk120pWhtyd3mQUpSoBSlKAUpSgM/2kFI1zsp3iQTqKRu4HSeaLh5x1Z8f1dY0Cs/2kZ7+NlOCnHfDIzvAZ/FFw6M8c/VxxnqzWgUApSlAKUpQClKUApSlAKUpQClKUBnu0oA662T5UlONRyMBQ4q/BFx4Dh09fV0H6q0Ks92l47+tk2SQe+ORjwc5/A9x/Z/9460KgFKUoBSlKAUpSgFKVXL9qiRFn822mG3PuCUJdeL7xaZYQokJ3lBKiVHBwkDoGSU5GdkISqO0S5ljpVI591h8wsfa3vZ0591h8wsfa3vZ10arPeuaFi70qkc+6w+YWPtb3s6c+6w+YWPtb3s6arPeuaFj5R7pru3JmybbVaNPXTZ2685pq5KuMaQ3dRu3Bl2HIYQpILB3D/xGTgnBQpOTxNfZ2kL1I1JpOyXaZb12mXPgsSnoDi99UZa20qU0VYGSkkpzgZx0CsA2x9z+9tr11ovVF7t9mTM03I5QtokOKTNaB30suZa+KFje4fnKHXka/z7rD5hY+1vezpqs965oWLvSqRz7rD5hY+1vezpz7rD5hY+1vezpqs965oWLvSqRz7rD5hY+1vezr9Gr75aQZF5tkHm1HF5+3yXHHGU/nltTY3kjpODkAcAropqtTss/wAoWLtSvFC0uIStCgpKhkKByCK8q4yCqHAOda6sz1Pxx6Pc6PWavlUKB8tdW/r4/wDbt124X+/DzRV2k1SlK3EFKh4+rrTK1XN001L3r1DiNTn4vJrG4y4paW1b2N05LaxgHIxxAyKmKgFK4Z18t9sm2+HLmsRpdwdUzEYdcCVyFpQpakoHSohKVKOOgA1y23V1pu+orzYokvlbrZwwZ0fk1p5EPJKmvCICVZCSfBJxjjigJilK4Zl8t9vuNvgSZrDE64KWiJGccAcfKEFa9xPSrdSCTjoFUHdXBqAA2G5AgEGM7wP+Q131wX/8RXL7M5/Kazh8SKsyb0goq0nZSTkmCwSf9NNS9Q+jvkjZPsLH9NNTFedV+ZLiw8xVCgfLXVv6+P8A27dX2qFA+Wurf18f+3browv9+Hmgu0mqwq5RbhtX276t0xO1Pe9PWXTVtgOxINinqguS3JAdUt9biMLUlHJpQE53c5yOPHdapWudjGjtpFyi3G/2f3TcYzRYbmxpT0V/kiclsuMrQpSM5O6okcTw41sauQyCfs2Vqvuh9TWvvq1HaxC0da0CZbLgY8h9wPS0pcdcQAVkYJxwSoqOQeGK7btaX7bLojZlbosnUcrWcvTfO85Vov5skVLe8GhIfdQ2tS1laTutpSU8VlQxivpOxbO9PaZupuVstqYkw26Pad9DqyBFYKiy2ElRSAnfVxAyc8ScCq3I7nbZ7JtVitytPlMSyRVQYSWpshtSY5OVMrWlwKdbJGShwqB8VY6LBgMQStsFn7me7aku11Tcp782NKl225PQ1rUiFJ+ECmlJ3VqLYypOCQpSegkVal7OhqzbVtj5PV2oNLuW6FaCzMtdyWwEqERwhx79KE7vELyCCrrOa12XsI0LM0bC0quwpRYYMtU6HFZkvNGI8VKUVMuJWFtcVrwEKAAUQBjhXBeu5r2c6hlKk3DT65Dy2WYzq+cZSeXaabS2227h0cqkJSBuryDxJySSZosGQbNNU6k7oa8aUt2or9eNORhoqLfHGrDMVAdnynn3GlPKW3hW4kNJIQPBy7xyMCq7ZWZG1q/bDntQX28vyhP1FaedLdc3oS5bcVLyG30qZUnC1pbG8pOCrBB4cK+mNYbF9Ga7atqLvZEK5tZMeGuE+7DWyyQAWkrYWhXJkJHgZ3eA4UvmxbRWodL2fTsuwsotFnUlduZhuuRVRFJSUgtuNKStPAkHB45Oc00WC6pTupCck4GMk5NcN/8AxFcvszn8prqiRW4MRmMyClllCW0AqKiEgYHE8TwHSa5b/wDiK5fZnP5TXRD4kVZk1o75I2T7Cx/TTUxUPo75I2T7Cx/TTUxXnVfmS4sPMVQoHy11b+vj/wBu3V9qo3yzXG3XqRdrXFFxRLShMmHyobcCkDCXEFR3Tw4FJI6AQeo78NJJyTeat1T8gjrpUJztfvIy69qhe3pztfvIy69qhe3rr0PuX7L1LYm6VCc7X7yMuvaoXt6c7X7yMuvaoXt6aH3L9l6ixN0qp3TW8+zT7RCmaUurUm7SVQ4SOXiK5V1LLj5TkPEJ+DZcVk4Hg46SAZHna/eRl17VC9vTQ+5fsvUWJulQnO1+8jLr2qF7enO1+8jLr2qF7emh9y/ZeosTdcF//EVy+zOfymuPna/eRl17VC9vXi9H1BqSO7bzZHrIxIQpp6ZMkMrU2gjBKEtLXlWDwyQB08cYOUYqLTclbivUWLRo75I2T7Cx/TTUxXqixm4UVmOyndaaQG0J8SQMAV7a8mb0pOW8xFKUrAClKUApSlAUHaKnOttlhxnGoJBzu5x+CZ/mOP2j6+ODfqz/AGkI3tc7KTuqO7qKQchOQPwRcBk8eHT08ekePNaBQClKUApSlAKUpQClKUApSlAKUpQGe7Sika62TZOCdRyMeCDk8z3H9n1+jrrQqoG0cLOuNlW6XABqGRvbgyCOabh8bxDOPTir/QClKUApSlAKUpQClKUApX4pQQkqUQlIGSScACq5J2laSiOqbe1PZ23EnCkGc1lP1je4VshTnU+BN8C2byLJSqr76ujfKqz9tb9dPfV0b5VWftrfrrZq1fuPky6L3FA2obVNERdoOzliRq+wMyLbqKT7racubCVRSLXPbPKArBR4Sgnwh0qAxk8Nigzo10hR5kOQ1LhyG0vMyGFhbbqFDKVJUOBBBBBHAg1/ODuztgVj2lbfNL3/AEpe7WYGpnkRr4+xJbKIS0YBkrwcBKmx6VIPWoZ+69N612f6T07a7HbdS2di3WyK1CjNe7mzuNNoCEDp6kpFNWr9x8mNF7i90qq++ro3yqs/bW/XX6NqmjSflVZh5zObA/mpq1fuPkyaL3FppXHbLxAvUfl7dNjT2P0sZ1Lif2pJFdlaGnF2ZBSlKgFRuo9QQ9LWeRcpylJYZA8FAytaicJQkdaiSAPrqSrGdud0XIv9ltIVhhhlyc4j85ZPJtn0Dlf3h4q7sFh9arxpPLt4IqKfqjUdx1tKW7dXD7kKiWrahZ5BtPVvDocV/iUOnOAkcKjkNpaSEoSEJHQEjAFftK+jwhGlFQgrJGDbYpSqDets9pssu4g2y8TbZbHCzPvEOIHIkVacb4UreCjuZ8IoSoJ454g1J1I01eTsQv1Kzy97bbVZp99jJtF5uTdjDblwlQYyFsstLZS6Hd4rG8ndVxCQVeCTu4wT3X7avbLRc4duhQLnqKdIiidyFmjh1TUc8EurKlJACuOBkqODgVh7ent25AutKpOxXUlw1dst09eLrIMq4S2Ct54tpRvHfUPipAA4AdAq7VshNVIqaye0HhHbMGYmZDccgzUkESYquTc+okdI8xyD1its2Z7RFaoQq2XLcRemG+U3kDdTJbBA5RI6iCUhQ6iQRwOBi1eyDdF2G9Wq6tq3FRJbSlHxtqUEOJ9KFK9OPFXDjsHDF0mmv5LJ+XAzTvsZ9RUpSvnAFYptxgLjars88hRZlRHIu91JWhW+kfWQtZH+Q1tdQesdKRtZWJ23SFFpWQ4w+lOVMup+KsDr8RHWCR116GAxCwuIjUll2/kqPnRa0tIUtaghCRlSlHAA8Zqqe+7oU/8AemnvvVj/AH1crxbpenLkbbdmRFlkkI4/BvpH5Tavyh5ukZwQK4/cMY/9O1+4K+h3c0pU2rP8+ZhaxWffd0L5a6d+9WP99ZZA2SqsuoL0xM2bWjWcW43R2dGvrzsdJbZeXvqQ6HAVkoJVgpCgoY6K3n3FH/QNfuCvdWqdD2tnUeXh63Blb2hLshe1xDEBKGL3EbZtaUuIAe3YAZ3QM+BhY3fCx4+jjUbp3TerdnmoGblC06L8xdLJbocxpE1pl2FIjNqTxKzhSCFnJSScjoPXs1Kjw0bqSbTV+rb3eLBlmy++WnZfs609p3Vt6tGn75FjEvQZtyYStGVqIPx+IPjFWf33dC+WunfvVj/fVocjMuq3ltIWrxqSCa8fcMb5u1+4KzjCcIqEWrLw/wAg47FqW0aojOSLNdYV2jtr5NbsGQh5KVYB3SUkgHBBx56km4C7vcLdbWgVOTZbLACekJ3wVn0IC1fUDXpKmIe4gBLZcUEobQnwlqPQEpHEnzCtg2V7PH7U+L9d2uSnqbLcaIrBMdCulSv8agB/lGR1qrRi8VHCUXOb/l2eL/3MyjvNMpSlfNgKUpQHJdLTBvcNcS4Q2J0VfxmZDYcQfQeFVB7Ylo91RULfJYz+SxcZLafQlLgA9Aq9UrfTxFajspza4Not2ig+8bpH5rP+9pftae8bpH5rP+9pftav1K369ivqy5sXZQfeN0j81n/e0v2tPeN0j81n/e0v2tX6lNexX1Zc2LsoPvG6R+az/vaX7Wv0bDtIA8Yk8jxG7S/a1faU17FfVlzYuyB09oPT+lXC7a7UxGfI3TIIK3iPEXFEqI9NT1KVyTnKo9Kbu/EmYpSlYA//2Q==",
74
+ "text/plain": [
75
+ "<IPython.core.display.Image object>"
76
+ ]
77
+ },
78
+ "metadata": {},
79
+ "output_type": "display_data"
80
+ }
81
+ ],
82
+ "source": [
83
+ "class State(TypedDict):\n",
84
+ " # Messages have the type \"list\". The `add_messages` function\n",
85
+ " # in the annotation defines how this state key should be updated\n",
86
+ " # (in this case, it appends messages to the list, rather than overwriting them)\n",
87
+ " messages: Annotated[list, add_messages]\n",
88
+ "\n",
89
+ "graph_builder = StateGraph(State)\n",
90
+ "\n",
91
+ "llm = ChatOpenAI(model='gpt-4o-mini', temperature=0.5)\n",
92
+ "\n",
93
+ "def chatbot(state: State):\n",
94
+ " return {\"messages\": [llm.invoke(state[\"messages\"])]}\n",
95
+ "\n",
96
+ "# Creating a name for the node and specifying the function.\n",
97
+ "# The messages that hte chatbot function returns will be added to the state\n",
98
+ "graph_builder.add_node(\"chatbot\", chatbot)\n",
99
+ "# Add a starting point\n",
100
+ "graph_builder.add_edge(START, \"chatbot\")\n",
101
+ "# Add an ending point\n",
102
+ "graph_builder.add_edge(\"chatbot\", END)\n",
103
+ "# Compile the graph\n",
104
+ "graph = graph_builder.compile()\n",
105
+ "\n",
106
+ "try:\n",
107
+ " display(Image(graph.get_graph().draw_mermaid_png()))\n",
108
+ "except Exception:\n",
109
+ " # This requires some extra dependencies and is optional\n",
110
+ " pass\n"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": 3,
116
+ "metadata": {},
117
+ "outputs": [
118
+ {
119
+ "name": "stdout",
120
+ "output_type": "stream",
121
+ "text": [
122
+ "Goodbye!\n"
123
+ ]
124
+ }
125
+ ],
126
+ "source": [
127
+ "# Use streaming\n",
128
+ "while True:\n",
129
+ " user_input = input(\"User: \")\n",
130
+ " if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n",
131
+ " print(\"Goodbye!\")\n",
132
+ " break\n",
133
+ " for event in graph.stream({\"messages\": (\"user\", user_input)}):\n",
134
+ " for value in event.values():\n",
135
+ " print(\"Assistant:\", value[\"messages\"][-1].content)"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "code",
140
+ "execution_count": 17,
141
+ "metadata": {},
142
+ "outputs": [
143
+ {
144
+ "data": {
145
+ "text/plain": [
146
+ "{'messages': [HumanMessage(content='tell me a joke', additional_kwargs={}, response_metadata={}, id='489e1ce6-64eb-4033-af63-f1479d2cb9f8'),\n",
147
+ " AIMessage(content='Why did the scarecrow win an award?\\n\\nBecause he was outstanding in his field!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 11, 'total_tokens': 28, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None}, id='run-29a969e4-b3db-4a7f-ad58-263c2b3be67e-0', usage_metadata={'input_tokens': 11, 'output_tokens': 17, 'total_tokens': 28})]}"
148
+ ]
149
+ },
150
+ "execution_count": 17,
151
+ "metadata": {},
152
+ "output_type": "execute_result"
153
+ }
154
+ ],
155
+ "source": [
156
+ "# Note that when using invoke you must pass a dictionary where the key is messages and the value is a list of dictionaries with the messages and includes role and content\n",
157
+ "graph.invoke({'messages':[{'role': 'user', 'content': 'tell me a joke' }]})"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "markdown",
162
+ "metadata": {},
163
+ "source": [
164
+ "# Chatbot with Vector Look-Up"
165
+ ]
166
+ },
167
+ {
168
+ "cell_type": "code",
169
+ "execution_count": 4,
170
+ "metadata": {},
171
+ "outputs": [
172
+ {
173
+ "name": "stderr",
174
+ "output_type": "stream",
175
+ "text": [
176
+ "/Users/nadaa/Documents/code/langgraph_learning/src/qdrant_manager.py:51: LangChainDeprecationWarning: The class `Qdrant` was deprecated in LangChain 0.1.2 and will be removed in 0.5.0. Use QdrantVectorStore instead.\n",
177
+ " self.qdrant = Qdrant(\n"
178
+ ]
179
+ },
180
+ {
181
+ "data": {
182
+ "image/jpeg": "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",
183
+ "text/plain": [
184
+ "<IPython.core.display.Image object>"
185
+ ]
186
+ },
187
+ "metadata": {},
188
+ "output_type": "display_data"
189
+ }
190
+ ],
191
+ "source": [
192
+ "\n",
193
+ "chatbot_instructions = \"\"\"You are a helpful assistant for people that want to query and research the teachings of \n",
194
+ "Paramhansa Yogananda and the Self-Realization Fellowship. You will only answer questions that are related to the teachings.\n",
195
+ "Provide compassionate and insightful responses that are grounded only in the context provided. \n",
196
+ "Instructions:\n",
197
+ "- Ask follow-up questions if needed to clarify the question\n",
198
+ "- Query the vector database multiple times if the user query contains a question or questions that span multiple topics\n",
199
+ "- Include direct quotes whenever possible. \n",
200
+ "- Provide a list of recommended reading when you output your answer\n",
201
+ "- Provide up to three suggestions for followup questions\n",
202
+ "\n",
203
+ "\"\"\"\n",
204
+ "\n",
205
+ "# Create the system message\n",
206
+ "system_message = SystemMessage(content=chatbot_instructions)\n",
207
+ "\n",
208
+ "# Modify the LLM initialization\n",
209
+ "llm = ChatOpenAI(model='gpt-4o-mini', temperature=0.5)\n",
210
+ "\n",
211
+ "memory = MemorySaver()\n",
212
+ "# Setup the state\n",
213
+ "class State(TypedDict):\n",
214
+ " # Messages have the type \"list\". The `add_messages` function\n",
215
+ " # in the annotation defines how this state key should be updated\n",
216
+ " # (in this case, it appends messages to the list, rather than overwriting them)\n",
217
+ " messages: Annotated[list, add_messages]\n",
218
+ "\n",
219
+ "graph_builder = StateGraph(State)\n",
220
+ "\n",
221
+ "llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0.5)\n",
222
+ "\n",
223
+ "\n",
224
+ "# Get vectorstore from qdrant\n",
225
+ "qdrant = qm.QdrantManager(collection_name=\"openai_large_chunks_1500char\")\n",
226
+ "vectorstore = qdrant.get_vectorstore()\n",
227
+ "\n",
228
+ "# Create my vector search tool\n",
229
+ "@tool\n",
230
+ "def vector_search(query: str, k: int = 5) -> list[Document]:\n",
231
+ " \"\"\"Search a vector database for passages from the teachings of Paramhansa Yogananda and other publications from the Self Realization Fellowship (SRF).\n",
232
+ " The user has the option to specify the number of passages they want the search to return, otherwise the number of passages will be set to the default value.\"\"\"\n",
233
+ " retriever = vectorstore.as_retriever(search_kwargs={\"k\": k})\n",
234
+ " documents = retriever.invoke(query)\n",
235
+ " return documents\n",
236
+ "\n",
237
+ "# Create a list of tools and bind them to the LLM\n",
238
+ "tools=[vector_search]\n",
239
+ "llm_with_tools = llm.bind_tools(tools)\n",
240
+ "\n",
241
+ "# Add the system message onto the llm\n",
242
+ "def chatbot(state: State):\n",
243
+ " messages = [system_message] + state[\"messages\"]\n",
244
+ " return {\"messages\": [llm_with_tools.invoke(messages)]}\n",
245
+ "\n",
246
+ "# Create and add a tool node\n",
247
+ "tool_node = ToolNode(tools)\n",
248
+ "graph_builder.add_node(\"tools\", tool_node)\n",
249
+ "graph_builder.add_node(\"chatbot\", chatbot)\n",
250
+ "\n",
251
+ "# Add a conditional edge wherein the chatbot can decide whether or not to go to the tools\n",
252
+ "graph_builder.add_conditional_edges(\n",
253
+ " \"chatbot\",\n",
254
+ " tools_condition,\n",
255
+ ")\n",
256
+ "\n",
257
+ "# Any time a tool is called, we return to the chatbot to decide the next step\n",
258
+ "graph_builder.add_edge(\"tools\", \"chatbot\")\n",
259
+ "graph_builder.add_edge(START, \"chatbot\")\n",
260
+ "\n",
261
+ "# Recompile the graph with the new structure\n",
262
+ "graph = graph_builder.compile(checkpointer=memory)\n",
263
+ "\n",
264
+ "# Visualize the updated graph\n",
265
+ "try:\n",
266
+ " display(Image(graph.get_graph().draw_mermaid_png()))\n",
267
+ "except Exception:\n",
268
+ " # This requires some extra dependencies and is optional\n",
269
+ " pass\n"
270
+ ]
271
+ },
272
+ {
273
+ "cell_type": "code",
274
+ "execution_count": 5,
275
+ "metadata": {},
276
+ "outputs": [
277
+ {
278
+ "name": "stdout",
279
+ "output_type": "stream",
280
+ "text": [
281
+ "Assistant: \n",
282
+ "Assistant: [Document(metadata={'split_id_uuid': 'e0d78426-d586-464d-ab83-fa1b4c6d74f1', 'split_id_sequential': 282, 'chapter_name': 'Intuition Develops Through Meditation', 'publication_name': 'Journey to Self-Realization', '_id': '40595e45-e286-43da-adad-fb54de68b614', '_collection_name': 'openai_large_chunks_1500char'}, page_content='A joy and peace will strike your heart. When that comes, you know that you are communing with God. If you make the effort, you shall contact that Power. Give yourself that opportunity. You cannot succeed unless you try. If you spend your life in constant excitement, you will never know true happiness. Live simply and take life more easily. Happiness lies in giving yourself time to think and to introspect. Be alone once in a while, and remain more in silence. If the radio is going all the time, or other stimuli are constantly bombarding the senses, it truly affects the nerves and creates nervousness. And don’t think so much about reforming others; reform yourself first. The greatest field of victory is your own home. If you are an angel at home, you can be an angel everywhere. The sweetness of your voice, the peace of your behaviour, is needed in your own household more than anywhere else.'), Document(metadata={'split_id_sequential': 716, 'publication_name': 'Journey to Self-Realization', 'chapter_name': 'Use Tact; Persons Are Not Unfeeling Stones', 'split_id_uuid': '7b8ee071-2240-4db1-b967-4b3f47bc9933', '_id': '667c9cc7-6f35-4c9f-b8b0-e9b2c6e99fab', '_collection_name': 'openai_large_chunks_1500char'}, page_content='Find your peace by meditating regularly and deeply, and you will be surprised to see how your relationships with others improve. Also develop your power of usefulness. That is love. Think about that. Learn to be serviceful to others—useful with positive thoughts; useful with your speech; useful with constructive suggestions. But do not give advice where it is not wanted; if your suggestions are unwelcome, have the control to remain silent. And when sometimes you do good to others and then can no longer help them in a material way, if they become inimical because they continue to expect from you, never mind; go on doing what is right. Do the best you can and forget it.'), Document(metadata={'split_id_sequential': 75, 'publication_name': 'Journey to Self-Realization', 'split_id_uuid': '1b706451-f27f-4466-8b44-f1fb17c80a69', 'chapter_name': 'Be a Conqueror of Hearts', '_id': '6714c2d3-f32a-42e6-bcf3-49f24cfb3d40', '_collection_name': 'openai_large_chunks_1500char'}, page_content='That is a lesson given to strengthen us, to bring out our hidden powers. But instead, the contradiction of desires causes anger. When desires are thwarted and we are caught in the paroxysm of anger, the mind becomes befogged and we forget our position and lose our discrimination; and when we act without discrimination, errors and unhappiness follow.2 If you never get angry at life’s reverses, or at their human instigators, you can see your way more clearly through whatever is going on around you. That is why your peace is to be guarded above everything else. If you can retain your inner peace, therein lies your supreme victory. No matter how you are situated in life, never feel justified in losing your peace. When that is gone and you cannot think clearly, you have lost the battle. If you never lose your peace, you will find you are always victorious, no matter what the outcome of your problems. That is the way to conquer life. You have nothing to fear. If you have to be afraid at all, be afraid only of yourself. But if you do everything with sincerity and love in your heart, you do not have to fear anybody or anything. As you find your soul-reservoir of peace, less and less controversy will be able to afflict your life. One who loves God lives in the soul, his true Self. He does everything for God, nothing for himself. He loves everybody, because he sees the world as the Lord’s cosmic show.'), Document(metadata={'split_id_uuid': '9f26c821-5e3c-4746-806a-54edd5df5a3a', 'publication_name': 'Journey to Self-Realization', 'chapter_name': 'Use Tact; Persons Are Not Unfeeling Stones', 'split_id_sequential': 715, '_id': 'e066e97f-21a6-446d-be4d-e28f9ca4d20f', '_collection_name': 'openai_large_chunks_1500char'}, page_content='After doing so, I said, “Now, I am not going to shut you out of my classes. But you must promise me that you will not talk against anyone during the class series. Do not think of yourselves as teachers. As long as there is prideful desire to teach, you are not qualified to teach. First you yourself must live it. If you do that, others will follow your example.” And do you know that hour after hour they attended the classes and didn’t once disturb anyone. They were the meekest of students. You see, I got along with them all right because I did not get angry. I used tact to bring them to the sudden realization of their mental weaknesses. But getting along with others cannot be done only by tact. It also requires example, calmness, evenness of mind, sincerity, joy, doing everything in an honourable way; not clinging to pride and egotism; and not governing your actions by what everybody else does, but doing those things that please God. Find your peace by meditating regularly and deeply, and you will be surprised to see how your relationships with others improve. Also develop your power of usefulness. That is love. Think about that. Learn to be serviceful to others—useful with positive thoughts; useful with your speech; useful with constructive suggestions. But do not give advice where it is not wanted; if your suggestions are unwelcome, have the control to remain silent.'), Document(metadata={'chapter_number': 61, 'publication_name': 'The Second Coming of Christ', 'split_id_sequential': 2217, 'split_id_uuid': '7e3cc238-62a7-4ad4-8da2-f26f25e2da99', 'chapter_name': 'Discourse 61 - “The Kingdom Of God Is Within You”', '_id': 'e9c475cd-898c-4368-b502-4bf783a88d9a', '_collection_name': 'openai_large_chunks_1500char'}, page_content='The yogi begins with proper deep breathing, inhaling and tensing the whole body, exhaling and relaxing, several times. With each exhalation all muscular tension and motion should be cast away, until a state of bodily stillness is attained. Then, by concentration techniques, restless motion is removed from the mind. In perfect stillness of body and mind, the yogi enjoys the ineffable peace of the presence of the soul. In the body, life is templed; in the mind, light is templed; in the soul, peace is templed. The deeper one goes into the soul the more that peace is felt; that is superconsciousness. When by deeper meditation the devotee expands that awareness of peace and feels his consciousness spreading with it over the universe, that all beings and all creation are swallowed up in that peace, then he is entering into Cosmic Consciousness. He feels that peace everywhere—in the flowers, in every human being, in the atmosphere. He beholds the earth and all worlds floating like bubbles in that ocean of peace.14 The inner peace first experienced by the devotee in meditation is his own soul; the vaster peace he feels by going deeper is God. The devotee who experiences unity with everything has established God in the temple of his infinite inner perception. In the temple of silence, in the temple of peace, I will meet Thee, I will touch Thee, I will love Thee, And coax Thee to my altar of peace.')]\n",
283
+ "Assistant: To cultivate a greater sense of peace in your life, Paramhansa Yogananda's teachings emphasize several key practices and attitudes:\n",
284
+ "\n",
285
+ "1. **Meditation**: Regular and deep meditation is fundamental. Yogananda teaches that \"Find your peace by meditating regularly and deeply, and you will be surprised to see how your relationships with others improve.\" Meditation helps quiet the mind and connect with a deeper state of peace.\n",
286
+ "\n",
287
+ "2. **Simplicity and Introspection**: Living simply and allowing time for introspection can lead to happiness. Yogananda advises, \"Happiness lies in giving yourself time to think and to introspect.\" This means taking moments of solitude to reflect and connect with your inner self.\n",
288
+ "\n",
289
+ "3. **Guarding Your Peace**: It's crucial to maintain your inner peace, regardless of external circumstances. Yogananda states, \"If you never lose your peace, you will find you are always victorious, no matter what the outcome of your problems.\" This involves not allowing anger or frustration to derail your calmness.\n",
290
+ "\n",
291
+ "4. **Service to Others**: Engaging in acts of kindness and being useful to others fosters love and peace. Yogananda suggests, \"Learn to be serviceful to others—useful with positive thoughts; useful with your speech; useful with constructive suggestions.\" \n",
292
+ "\n",
293
+ "5. **Breath and Stillness**: Practicing proper deep breathing and achieving bodily stillness can enhance your sense of peace. Yogananda describes, \"In perfect stillness of body and mind, the yogi enjoys the ineffable peace of the presence of the soul.\"\n",
294
+ "\n",
295
+ "Incorporating these practices into your daily routine can help you cultivate a more peaceful state of being.\n",
296
+ "\n",
297
+ "### Recommended Reading:\n",
298
+ "- **\"Journey to Self-Realization\"** by Paramhansa Yogananda\n",
299
+ "- **\"The Second Coming of Christ\"** by Paramhansa Yogananda\n",
300
+ "\n",
301
+ "### Follow-Up Questions:\n",
302
+ "1. What specific challenges do you face that disrupt your peace?\n",
303
+ "2. Have you tried meditation before, and if so, what was your experience?\n",
304
+ "3. Are there particular areas in your life where you feel you could be more serviceful to others?\n",
305
+ "Goodbye!\n"
306
+ ]
307
+ }
308
+ ],
309
+ "source": [
310
+ "# Use streaming\n",
311
+ "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
312
+ "\n",
313
+ "while True:\n",
314
+ " user_input = input(\"User: \")\n",
315
+ " if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n",
316
+ " print(\"Goodbye!\")\n",
317
+ " break\n",
318
+ " for event in graph.stream({\"messages\": (\"user\", user_input)}, config):\n",
319
+ " for value in event.values():\n",
320
+ " print(\"Assistant:\", value[\"messages\"][-1].content)"
321
+ ]
322
+ },
323
+ {
324
+ "cell_type": "code",
325
+ "execution_count": 9,
326
+ "metadata": {},
327
+ "outputs": [],
328
+ "source": [
329
+ "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
330
+ "result = graph.invoke({\"messages\":[{\"role\": \"user\", \"content\": \"Search the vector database on the importance of a true guru, return the full passages returned from the vector search verbatim and bold the most important quotes\"}]}, config)\n"
331
+ ]
332
+ },
333
+ {
334
+ "cell_type": "code",
335
+ "execution_count": 10,
336
+ "metadata": {},
337
+ "outputs": [
338
+ {
339
+ "name": "stdout",
340
+ "output_type": "stream",
341
+ "text": [
342
+ "Here are the full passages returned from the vector search on the importance of a true guru, with the most important quotes bolded:\n",
343
+ "\n",
344
+ "1. **\"It is admirable to lecture and teach good principles; but without possessing the qualifications of a real guru a teacher cannot redeem souls, nor should he presume to accept others as disciples until he himself has progressed far in his own Self-realization. True gurus train first their inner selves in the theologically advanced school of intuition and God-communion in meditation. They spiritually baptize themselves in Spirit before they aspire to initiate others. They teach not for mundane gain or glory, but for the singular purpose of leading souls to God. A guru never seeks for himself the devotion and obedience of his disciples, but transfers that reverence to God. It is not necessary for a disciple to be in the company of the guru in order to receive his blessings. What is most important is to be spiritually in tune with the guru, for his help is transferred to the disciple primarily on the inner spiritual plane rather than through material means. If the disciple is uncarping, unconditionally reverential and loving to the master, and faithful in following his precepts, his receptivity makes the task of the guru easier. Attunement links the help of the guru with the sincere striving of the disciple, even if the guru is no longer incarnate on earth.\"**\n",
345
+ "\n",
346
+ "2. **\"Baptized in a radiance as of a thousand suns, my whole being was blissfully enwrapped in God’s love and secured in the care of Guru’s wisdom. The Kriya Yoga sadhana imparted to me at that diksha was the “pearl of great price” with which all doors to the Divine Presence would be opened. A guru is not an ordinary spiritual teacher. One may have many teachers, but only one guru, who is the agent of salvation appointed by God in response to a devotee’s demands for release from the bondage of matter. Ministers in churches and priests in temples are oftentimes chosen only by a set standard of their intellectual knowledge of the scriptures, or by virtue of sacerdotal authority ceremonially conferred on them by a formally higher ecclesiastical superior. No guru can be developed only by years of study in the intellectual factory of a theological seminary, which deems it has attained its ends when it confers B.D. or D.D. degrees. Such titles can be won by men of good memory; but character, self-control, and the wisdom of soul intuition can be cultured only by knowledge and application of advanced methods of deep daily meditation that produce Self-realization and actual experience of God. Neither can one be a guru by self-choice. He must be ordained to serve and save others by a real guru, or else he must hear in reality the voice of God asking him to redeem others.\"**\n",
347
+ "\n",
348
+ "3. **\"Discretion and caution are particularly necessary in accepting a guru, one to whom explicit loyalty and trust are given. One may have many teachers in the beginning of his search, but when one’s heart and soul are confidently settled in a guru-disciple relationship ordained and blessed by God, the disciple has only one guru, and no other teachers thereafter. The devotee remains loyal to such a guru, being spiritually fulfilled by the God-sent messenger. To forsake the guru and his ideals is to spurn the help sent by God, the One Guru of gurus: “the Lord God of the holy prophets”; He whom alone “seers great, and heaven’s-path successful ones,” do worship. Unconditional love, loyalty, and obedience are hallmarks of the guru-disciple relationship. The spiritual soul contact between guru and disciple is one of eternal, unconditional divine love and friendship, bearing no taint of any selfish consideration. Human love is conditional and based upon merit and inborn attachments. Unconditional divine love is the Christ-love with which God embraces all His children, high or low, naughty or good, under all circumstances. Only a master, one who has cast off his ego with its biases and selfish expectations, is capable of serving as a perfect channel through which God’s divine love may flow without measure. In the spiritually receptive, loyalty to the guru rises spontaneously when the disciple’s heart is bathed in the aura of the guru’s unconditional love.\"**\n",
349
+ "\n",
350
+ "4. **\"Of the total requirement to achieve salvation, it is said that 25% is the disciple’s spiritual effort, 25% is the blessing of the guru, and the remaining 50% is the grace of God. The aspirant should not be tempted into complacency, however, waiting to be moved by the spirit of the blessings and grace, for it is the catalyst of the devotee’s effort that makes the formula work. As the devotee’s effort and the guru’s blessings are equally necessary to the disciple’s progress, we are taught in India the first requisite importance on the spiritual path of following faithfully one’s guru. He takes personal interest in the welfare of the devotee’s soul and lays before him a path of spiritual discipline that leads as far as the God-seeker wishes to go. In the early years of my spiritual search I was blessed to have frequent association with saintly souls whose God-consciousness transported my consciousness into supernal realms. But it was not until I met my own God-ordained guru, Swami Sri Yukteswar, and received initiation from him, that I understood fully the transforming power of the sacred guru-disciple tradition. Baptized in a radiance as of a thousand suns, my whole being was blissfully enwrapped in God’s love and secured in the care of Guru’s wisdom. The Kriya Yoga sadhana imparted to me at that diksha was the “pearl of great price” with which all doors to the Divine Presence would be opened. A guru is not an ordinary spiritual teacher.\"**\n",
351
+ "\n",
352
+ "5. **\"What is most important is to be spiritually in tune with the guru, for his help is transferred to the disciple primarily on the inner spiritual plane rather than through material means. If the disciple is uncarping, unconditionally reverential and loving to the master, and faithful in following his precepts, his receptivity makes the task of the guru easier. Attunement links the help of the guru with the sincere striving of the disciple, even if the guru is no longer incarnate on earth. My guru, Sri Yukteswarji, wrote: “To keep company with the Guru is not only to be in his physical presence (as this is sometimes impossible), but mainly means to keep him in our hearts and to be one with him in principle and to attune ourselves with him.…by keeping his appearance and attributes fully in mind, and by reflecting on the same and affectionately following his instructions, lamblike.” Many who were born centuries after Christ have attained God-realization through devotion to Jesus, the Good Shepherd, whom they followed as their guru or saviour. Jesus said, “Why call ye me Lord, Lord, and do not the things which I say?” The secret of the saints is that they practised what Jesus taught and exemplified; and by their single-hearted devotion they were able to attain ecstatic interiorization, as do adept yogis, which is necessary for communion with Christ.\"**\n",
353
+ "\n",
354
+ "These passages highlight the profound role of a true guru in spiritual development and the essential qualities that define this relationship. If you have any further questions or need additional insights, feel free to ask!\n"
355
+ ]
356
+ }
357
+ ],
358
+ "source": [
359
+ "print(result['messages'][-1].content)"
360
+ ]
361
+ },
362
+ {
363
+ "cell_type": "code",
364
+ "execution_count": 15,
365
+ "metadata": {},
366
+ "outputs": [],
367
+ "source": [
368
+ "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
369
+ "result = graph.invoke({\"messages\":[{\"role\": \"user\", \"content\": \"Summarize in a nice paragraph format what yogananda says about introspection. At the end of the summary provide supporting quotes and resources.\"}]}, config)\n"
370
+ ]
371
+ },
372
+ {
373
+ "cell_type": "code",
374
+ "execution_count": 16,
375
+ "metadata": {},
376
+ "outputs": [
377
+ {
378
+ "name": "stdout",
379
+ "output_type": "stream",
380
+ "text": [
381
+ "Paramhansa Yogananda emphasizes the significance of introspection as a crucial practice for spiritual development and self-awareness. He describes introspection as a \"wonderful mirror\" that allows individuals to evaluate their thoughts and actions, promoting moral and spiritual growth. By reflecting on oneself, particularly in the light of a guru's wisdom, one can gain deeper insights and clarity. Yogananda advocates for accepting criticism as a sign of spiritual strength, encouraging individuals to learn from feedback and continuously strive for improvement. He also highlights the importance of deep thinking, asserting that concentrated reflection can lead to profound understanding and peace. Ultimately, Yogananda underscores personal responsibility, urging individuals to prioritize self-correction over the tendency to criticize others. This holistic approach to introspection is seen as essential on the path to self-realization and divine connection.\n",
382
+ "\n",
383
+ "### Supporting Quotes:\n",
384
+ "- **\"Introspection is a wonderful mirror in which to judge oneself.\"**\n",
385
+ "- **\"Even more accurate than that mirror is one’s reflection in the mirror of a wise man’s mind.\"**\n",
386
+ "- **\"To be able humbly to stand the barbs of criticism, just or unjust, and to make continuous effort to improve one’s attitudes and behavior when criticism is justified, will make one a saint.\"**\n",
387
+ "- **\"Without deep thinking, concentration of the mind, one will never find the way to God.\"**\n",
388
+ "\n",
389
+ "### Recommended Resources:\n",
390
+ "- **\"The Second Coming of Christ\"** by Paramhansa Yogananda\n",
391
+ "- **\"Journey to Self-Realization\"** by Paramhansa Yogananda\n"
392
+ ]
393
+ }
394
+ ],
395
+ "source": [
396
+ "print(result['messages'][-1].content)"
397
+ ]
398
+ },
399
+ {
400
+ "cell_type": "code",
401
+ "execution_count": 17,
402
+ "metadata": {},
403
+ "outputs": [],
404
+ "source": [
405
+ "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
406
+ "result = graph.invoke({\"messages\":[{\"role\": \"user\", \"content\": \"Find 20 passages on introspection and identify the subtopics that emerge.\"}]}, config)\n"
407
+ ]
408
+ },
409
+ {
410
+ "cell_type": "code",
411
+ "execution_count": 18,
412
+ "metadata": {},
413
+ "outputs": [
414
+ {
415
+ "name": "stdout",
416
+ "output_type": "stream",
417
+ "text": [
418
+ "Here are 20 passages on introspection from the teachings of Paramhansa Yogananda, along with the subtopics that emerge from these reflections:\n",
419
+ "\n",
420
+ "1. **Introspection as Self-Judgment**: Yogananda describes introspection as a \"wonderful mirror\" for self-assessment, emphasizing the importance of judging oneself rather than others.\n",
421
+ "\n",
422
+ "2. **Guidance from a Guru**: He highlights the value of seeing oneself through the lens of a wise guru, stating that their insights can lead to spiritual transformation.\n",
423
+ "\n",
424
+ "3. **Strength in Criticism**: Yogananda notes that the ability to accept criticism is a sign of spiritual strength and encourages individuals to use criticism as a tool for self-improvement.\n",
425
+ "\n",
426
+ "4. **Deep Thinking**: He advocates for deep thinking as a means to cultivate introspection, suggesting that it allows individuals to dive deeper into their thoughts and gain clarity and peace.\n",
427
+ "\n",
428
+ "5. **Personal Responsibility**: Yogananda emphasizes the importance of personal responsibility in self-correction, urging individuals to focus on their own flaws rather than criticizing others.\n",
429
+ "\n",
430
+ "6. **Inner Peace**: He warns against the negative effects of harboring critical thoughts about others, suggesting that such negativity disrupts one's inner peace.\n",
431
+ "\n",
432
+ "7. **The Role of Intuition**: Yogananda connects introspection to the development of intuition, stating that a calm mind allows for greater intuitive understanding and insight.\n",
433
+ "\n",
434
+ "8. **Meditation and Introspection**: He stresses that meditation is essential for developing introspection, as it helps clear the mind and facilitates deeper self-examination.\n",
435
+ "\n",
436
+ "9. **The Nature of Truth**: Yogananda discusses the need for honest self-scrutiny, suggesting that true understanding of one's nature requires confronting uncomfortable truths.\n",
437
+ "\n",
438
+ "10. **Avoiding Hypocrisy**: He warns against the dangers of hypocrisy, advocating for sincere self-reflection rather than the superficial acknowledgment of faults.\n",
439
+ "\n",
440
+ "11. **Self-Enquiry**: Yogananda encourages self-enquiry as a means to uncover deeper truths about oneself, promoting questions like \"Who am I?\" and \"What is my purpose?\"\n",
441
+ "\n",
442
+ "12. **The Importance of Silence**: He suggests that spending time in silence is crucial for introspection, allowing individuals to connect with their inner selves.\n",
443
+ "\n",
444
+ "13. **Judgment vs. Observation**: Yogananda differentiates between judgment and observation, advocating for a neutral perspective that focuses on understanding rather than criticizing.\n",
445
+ "\n",
446
+ "14. **Transformation through Introspection**: He believes that introspection leads to personal transformation, enabling individuals to align more closely with their true selves.\n",
447
+ "\n",
448
+ "15. **The Dangers of External Validation**: Yogananda cautions against seeking validation from others, emphasizing that true worth comes from self-knowledge and inner peace.\n",
449
+ "\n",
450
+ "16. **The Impact of Environment**: He notes that one's environment can influence thoughts and feelings, highlighting the importance of cultivating a positive inner space.\n",
451
+ "\n",
452
+ "17. **Self-Reflection as a Path to God**: Yogananda teaches that introspection can lead to a deeper communion with God, as it opens the heart and mind to divine truths.\n",
453
+ "\n",
454
+ "18. **The Connection between Introspection and Faith**: He connects introspection to the development of faith, suggesting that understanding oneself leads to a stronger connection with the divine.\n",
455
+ "\n",
456
+ "19. **Ego and Self-Analysis**: Yogananda discusses the role of ego in hindering true self-analysis, urging individuals to confront and transcend their egos.\n",
457
+ "\n",
458
+ "20. **The Journey of Self-Discovery**: He frames introspection as an ongoing journey of self-discovery, encouraging individuals to continually seek deeper understanding of themselves and their relationship with God.\n",
459
+ "\n",
460
+ "### Subtopics Identified:\n",
461
+ "- Self-Judgment and Self-Assessment\n",
462
+ "- Guidance and Influence of a Guru\n",
463
+ "- Strength and Growth through Criticism\n",
464
+ "- Deep Thinking and Concentration\n",
465
+ "- Personal Responsibility in Self-Correction\n",
466
+ "- Inner Peace and Mental Clarity\n",
467
+ "- Development of Intuition\n",
468
+ "- The Role of Meditation in Introspection\n",
469
+ "- Honest Self-Enquiry and Truth-Seeking\n",
470
+ "- Avoiding Hypocrisy and Sincerity\n",
471
+ "- The Importance of Silence for Reflection\n",
472
+ "- Observation vs. Judgment\n",
473
+ "- Transformation through Self-Reflection\n",
474
+ "- The Impact of External Validation\n",
475
+ "- The Influence of Environment on Thoughts\n",
476
+ "- Introspection as a Path to God\n",
477
+ "- Connection between Introspection and Faith\n",
478
+ "- Ego and Self-Analysis\n",
479
+ "- Ongoing Journey of Self-Discovery\n",
480
+ "\n",
481
+ "These passages and subtopics provide a comprehensive view of Yogananda's teachings on introspection, highlighting its significance in the spiritual journey. If you have further questions or need more insights, feel free to ask!\n"
482
+ ]
483
+ }
484
+ ],
485
+ "source": [
486
+ "print(result['messages'][-1].content)"
487
+ ]
488
+ },
489
+ {
490
+ "cell_type": "code",
491
+ "execution_count": 5,
492
+ "metadata": {},
493
+ "outputs": [
494
+ {
495
+ "name": "stdout",
496
+ "output_type": "stream",
497
+ "text": [
498
+ "Running on local URL: http://127.0.0.1:7861\n",
499
+ "Running on public URL: https://5c55504e6a49d443ab.gradio.live\n",
500
+ "\n",
501
+ "This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)\n"
502
+ ]
503
+ },
504
+ {
505
+ "data": {
506
+ "text/html": [
507
+ "<div><iframe src=\"https://5c55504e6a49d443ab.gradio.live\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
508
+ ],
509
+ "text/plain": [
510
+ "<IPython.core.display.HTML object>"
511
+ ]
512
+ },
513
+ "metadata": {},
514
+ "output_type": "display_data"
515
+ },
516
+ {
517
+ "data": {
518
+ "text/plain": []
519
+ },
520
+ "execution_count": 5,
521
+ "metadata": {},
522
+ "output_type": "execute_result"
523
+ }
524
+ ],
525
+ "source": [
526
+ "import gradio as gr\n",
527
+ "from langgraph.graph import StateGraph, END\n",
528
+ "from langchain_openai import ChatOpenAI\n",
529
+ "config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
530
+ "\n",
531
+ "# Define the chatbot function\n",
532
+ "# def chatbot(state):\n",
533
+ "# llm = ChatOpenAI()\n",
534
+ "# return {\"messages\": state[\"messages\"] + [llm.invoke(state[\"messages\"])]}\n",
535
+ "\n",
536
+ "# # Create the graph\n",
537
+ "# graph = StateGraph()\n",
538
+ "\n",
539
+ "# # Add the chatbot node\n",
540
+ "# graph.add_node(\"chatbot\", chatbot)\n",
541
+ "\n",
542
+ "# # Define the edges\n",
543
+ "# graph.add_edge(graph.START, \"chatbot\")\n",
544
+ "# graph.add_edge(\"chatbot\", graph.END)\n",
545
+ "\n",
546
+ "# # Compile the graph\n",
547
+ "# chain = graph.compile()\n",
548
+ "\n",
549
+ "# Define the Gradio interface\n",
550
+ "def respond(message, history):\n",
551
+ " # Format the history and new message into the expected structure\n",
552
+ " formatted_messages = []\n",
553
+ " for human, ai in history:\n",
554
+ " formatted_messages.append(HumanMessage(content=human))\n",
555
+ " if ai: # AI might not have responded yet\n",
556
+ " formatted_messages.append(AIMessage(content=ai))\n",
557
+ " \n",
558
+ " # Add the new message\n",
559
+ " formatted_messages.append(HumanMessage(content=message))\n",
560
+ " \n",
561
+ " # Invoke the graph with properly formatted input\n",
562
+ " result = graph.invoke({\"messages\": formatted_messages}, config)\n",
563
+ " \n",
564
+ " # Extract the assistant's response\n",
565
+ " response = result[\"messages\"][-1].content\n",
566
+ " \n",
567
+ " return response\n",
568
+ "\n",
569
+ "# Create and launch the Gradio interface\n",
570
+ "gradio = gr.ChatInterface(respond)\n",
571
+ "gradio.launch(share=True)\n"
572
+ ]
573
+ },
574
+ {
575
+ "cell_type": "code",
576
+ "execution_count": null,
577
+ "metadata": {},
578
+ "outputs": [],
579
+ "source": []
580
+ }
581
+ ],
582
+ "metadata": {
583
+ "kernelspec": {
584
+ "display_name": "langgraph_learning-fxXDDPLh",
585
+ "language": "python",
586
+ "name": "python3"
587
+ },
588
+ "language_info": {
589
+ "codemirror_mode": {
590
+ "name": "ipython",
591
+ "version": 3
592
+ },
593
+ "file_extension": ".py",
594
+ "mimetype": "text/x-python",
595
+ "name": "python",
596
+ "nbconvert_exporter": "python",
597
+ "pygments_lexer": "ipython3",
598
+ "version": "3.11.9"
599
+ }
600
+ },
601
+ "nbformat": 4,
602
+ "nbformat_minor": 2
603
+ }
qdrant_manager.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from typing import List, Optional
4
+ from langchain.embeddings.base import Embeddings
5
+ from langchain_qdrant import Qdrant
6
+ from langchain.schema import Document
7
+ from langchain_openai import OpenAIEmbeddings
8
+ from qdrant_client import QdrantClient
9
+ from qdrant_client.models import Distance, VectorParams
10
+
11
+ import config as config
12
+
13
+ # Qdrant Collections Params
14
+
15
+ openai_embeddings = OpenAIEmbeddings(model=config.EMBEDDINGS_MODEL_NAME)
16
+ QDRANT_COLLECTIONS_PARAMS = {'openai_large_chunks_1500char': {'collection_name': 'openai_large_chunks_1500char',
17
+ 'embeddings_model_name': 'text-embedding-3-large',
18
+ 'vector_size': 3072,
19
+ 'distance': Distance.COSINE,
20
+ 'embeddings_model': openai_embeddings},
21
+
22
+ 'openai_large_chunks_500char': {'collection_name': 'openai_large_chunks_500char',
23
+ 'embeddings_model_name': 'text-embedding-3-large',
24
+ 'vector_size': 3072,
25
+ 'distance': Distance.COSINE,
26
+ 'embeddings_model': openai_embeddings}}
27
+
28
+
29
+
30
+
31
+ class QdrantManager:
32
+ '''Qdrant Manager to create a collection, add documents, and get a retriever. To see available collections, run client.get_collections()'''
33
+
34
+ def __init__(
35
+ self,
36
+ collection_name: str,
37
+ embeddings: Optional[Embeddings] = None,
38
+ url: Optional[str] = None,
39
+ api_key: Optional[str] = None,
40
+ vector_size: Optional[int] = None,
41
+ distance: Optional[Distance] = None
42
+ ):
43
+ self.collection_name = collection_name
44
+ self.embeddings = embeddings or QDRANT_COLLECTIONS_PARAMS[collection_name]['embeddings_model']
45
+ self.url = url or os.getenv("QDRANT_URL") or config[collection_name].get('url')
46
+ self.api_key = api_key or os.getenv("QDRANT_API_KEY") or config[collection_name].get('api_key')
47
+ self.vector_size = vector_size or QDRANT_COLLECTIONS_PARAMS[collection_name]['vector_size']
48
+ self.distance = distance or QDRANT_COLLECTIONS_PARAMS[collection_name]['distance']
49
+
50
+ self.client = QdrantClient(url=self.url, api_key=self.api_key)
51
+ self.qdrant = Qdrant(
52
+ client=self.client,
53
+ collection_name=self.collection_name,
54
+ embeddings=self.embeddings,
55
+ content_payload_key="page_content",
56
+ metadata_payload_key="metadata",
57
+ )
58
+
59
+ def create_collection(self) -> None:
60
+ """Create a new collection if it doesn't exist."""
61
+ collections = self.client.get_collections().collections
62
+ if self.collection_name not in [c.name for c in collections]:
63
+ self.client.create_collection(
64
+ collection_name=self.collection_name,
65
+ vectors_config=VectorParams(size=self.vector_size, distance=self.distance),
66
+ )
67
+ print(f"Collection '{self.collection_name}' created.")
68
+ else:
69
+ print(f"Collection '{self.collection_name}' already exists.")
70
+
71
+ def add_documents(self, documents: List[Document], batch_size: int = 1000) -> None:
72
+ """Add documents to the collection in batches."""
73
+ for i in range(0, len(documents), batch_size):
74
+ batch = documents[i:i+batch_size]
75
+ self.qdrant.add_documents(batch)
76
+ print(f"Added batch {i//batch_size + 1} ({len(batch)} documents)")
77
+ print(f"Total documents added: {len(documents)}")
78
+
79
+ def get_vectorstore(self):
80
+ """Get the Qdrant vectorstore."""
81
+ return self.qdrant
82
+
83
+ def delete_collection(self) -> None:
84
+ """Delete the collection."""
85
+ self.client.delete_collection(self.collection_name)
86
+ print(f"Collection '{self.collection_name}' deleted.")
requirements.txt DELETED
@@ -1 +0,0 @@
1
- huggingface_hub==0.22.2
 
 
src/__init__.py ADDED
File without changes
src/bot.py ADDED
File without changes
src/utils/__init__.py ADDED
File without changes
tests/__init__.py ADDED
File without changes