Skip to content

Commit 749817b

Browse files
committed
chatbot notebook
1 parent da1e0d9 commit 749817b

1 file changed

Lines changed: 364 additions & 0 deletions

File tree

chatbot.ipynb

Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"pip install langchain-experimental psutil gradio speechrecognition"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"# Import statements"
17+
]
18+
},
19+
{
20+
"cell_type": "code",
21+
"execution_count": 39,
22+
"metadata": {},
23+
"outputs": [],
24+
"source": [
25+
"from langchain_community.llms import Ollama\n",
26+
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
27+
"from langchain.memory import ChatMessageHistory\n",
28+
"from gradio.data_classes import FileData\n",
29+
"import time\n",
30+
"import gradio as gr\n",
31+
"import psutil\n",
32+
"import speech_recognition as sr"
33+
]
34+
},
35+
{
36+
"cell_type": "markdown",
37+
"metadata": {},
38+
"source": [
39+
"# Connect to locally running LLM by using Ollama"
40+
]
41+
},
42+
{
43+
"cell_type": "code",
44+
"execution_count": 40,
45+
"metadata": {},
46+
"outputs": [],
47+
"source": [
48+
"# This assumes that ollama is running on localhost at port 11434 and has \"mistral:instruct\" downloaded\n",
49+
"llm = Ollama(model=\"mistral:instruct\", num_thread = (psutil.cpu_count() - 2), keep_alive = -1, num_ctx=4098)\n",
50+
"# llm.invoke(\"Hi\") // test"
51+
]
52+
},
53+
{
54+
"cell_type": "markdown",
55+
"metadata": {},
56+
"source": [
57+
"# Create chain for conversational generation"
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": 41,
63+
"metadata": {},
64+
"outputs": [],
65+
"source": [
66+
"prompt = ChatPromptTemplate.from_messages([\n",
67+
" (\"system\",\"You are a helpful assistant named Atom. Answer all questions to the best of your ability.\"),\n",
68+
" MessagesPlaceholder(variable_name=\"messages\")\n",
69+
" ])\n",
70+
"\n",
71+
"chain = prompt | llm"
72+
]
73+
},
74+
{
75+
"cell_type": "markdown",
76+
"metadata": {},
77+
"source": [
78+
"# Create conversational memory for LLMs"
79+
]
80+
},
81+
{
82+
"cell_type": "code",
83+
"execution_count": 42,
84+
"metadata": {},
85+
"outputs": [],
86+
"source": [
87+
"ephemeral_chat_history = ChatMessageHistory()"
88+
]
89+
},
90+
{
91+
"cell_type": "markdown",
92+
"metadata": {},
93+
"source": [
94+
"# Extract contents of text files passed in by user in chat"
95+
]
96+
},
97+
{
98+
"cell_type": "code",
99+
"execution_count": 43,
100+
"metadata": {},
101+
"outputs": [],
102+
"source": [
103+
"def get_files_content(files):\n",
104+
" if len(files) > 0 :\n",
105+
" files_content=[]\n",
106+
" for FileData in files:\n",
107+
" with open(FileData[\"path\"],'r') as f:\n",
108+
" try:\n",
109+
" file_content = f.read()\n",
110+
" if file_content == \"\":\n",
111+
" print(f\"Warning : The '{FileData['path']}' file is empty. Skipping it..\")\n",
112+
" continue\n",
113+
" files_content.append(file_content)\n",
114+
" except:\n",
115+
" print(f\"Warning : Unable to read the contents of the file '{FileData['path']}'. Skipping it..\")\n",
116+
" continue\n",
117+
" if len(files_content) == 0:\n",
118+
" return False, \"\"\n",
119+
" content = \"\\n\\n\".join(files_content)\n",
120+
" return True, content\n",
121+
" return True, \"\""
122+
]
123+
},
124+
{
125+
"cell_type": "markdown",
126+
"metadata": {},
127+
"source": [
128+
"# Convert speech to text "
129+
]
130+
},
131+
{
132+
"cell_type": "code",
133+
"execution_count": 44,
134+
"metadata": {},
135+
"outputs": [],
136+
"source": [
137+
"def get_audio_content(audio):\n",
138+
" if audio == None:\n",
139+
" return True, \"\"\n",
140+
" try: \n",
141+
" r = sr.Recognizer()\n",
142+
" # audio object \n",
143+
" audio = sr.AudioFile(audio)\n",
144+
" #read audio object and transcribe\n",
145+
" with audio as source:\n",
146+
" audio = r.record(source) \n",
147+
" result = r.recognize_google(audio)\n",
148+
" except:\n",
149+
" return False, \"\"\n",
150+
" return True, \"\\n\\n\" + result + \"\\n\\n\""
151+
]
152+
},
153+
{
154+
"cell_type": "markdown",
155+
"metadata": {},
156+
"source": [
157+
"# Combine content from text files and speech to create context"
158+
]
159+
},
160+
{
161+
"cell_type": "code",
162+
"execution_count": 45,
163+
"metadata": {},
164+
"outputs": [],
165+
"source": [
166+
"def get_context(files, audio):\n",
167+
" file_status, file_context = get_files_content(files)\n",
168+
" audio_status, audio_context = get_audio_content(audio)\n",
169+
" context = \"\"\n",
170+
" context_status = True\n",
171+
" if not file_status:\n",
172+
" context = context + \"Error : Failed to read contents of all uploaded files or it was empty. Please try again and upload readable docs.\\n\"\n",
173+
" context_status = False\n",
174+
" if not audio_status:\n",
175+
" context = context + \"Error : Failed to convert audio to text or the audio was empty. Try again.\\n\"\n",
176+
" context_status = False\n",
177+
" \n",
178+
" if context_status:\n",
179+
" context = file_context + audio_context\n",
180+
" \n",
181+
" return context_status, context"
182+
]
183+
},
184+
{
185+
"cell_type": "markdown",
186+
"metadata": {},
187+
"source": [
188+
"# Generate prompt to feed LLM"
189+
]
190+
},
191+
{
192+
"cell_type": "code",
193+
"execution_count": 46,
194+
"metadata": {},
195+
"outputs": [],
196+
"source": [
197+
"def generate_prompt(context, question):\n",
198+
" if ' '.join(context.split()) == \"\" and question == \"\":\n",
199+
" return \"\"\n",
200+
" elif question == \"\":\n",
201+
" return f\"\"\"\n",
202+
" Can you provide a comprehensive summary of the given text? \n",
203+
" The summary should cover all the key points and main ideas presented in the original text, \n",
204+
" while also condensing the information into a concise and easy-to-understand format. \n",
205+
" Please ensure that the summary includes relevant details and examples that support the main ideas,\n",
206+
" while avoiding any unnecessary information or repetition. \n",
207+
" The length of the summary should be appropriate for the length and complexity of the original text, \n",
208+
" providing a clear and accurate overview without omitting any important information:\n",
209+
" \"{context}\"\n",
210+
" CONCISE SUMMARY:\n",
211+
" \"\"\"\n",
212+
" elif ' '.join(context.split()) == \"\":\n",
213+
" return question\n",
214+
" else:\n",
215+
" return f\"\"\"\n",
216+
" Analyze and examine the following document and answer the given question.\n",
217+
" Base your answer on the information provided in the document. \n",
218+
" If you cannot answer the question based on the document provided,\n",
219+
" then answer it based on your knowledge but specify that you are using external information.\n",
220+
" \n",
221+
" Document:\n",
222+
" \"{context}\"\n",
223+
"\n",
224+
" Question:\n",
225+
" \"{question}\"\n",
226+
"\n",
227+
" ANSWER:\n",
228+
" \"\"\""
229+
]
230+
},
231+
{
232+
"cell_type": "markdown",
233+
"metadata": {},
234+
"source": [
235+
"# Driver method"
236+
]
237+
},
238+
{
239+
"cell_type": "code",
240+
"execution_count": 47,
241+
"metadata": {},
242+
"outputs": [],
243+
"source": [
244+
"def slow_reply(message, history, audio):\n",
245+
" context_status, context = get_context(message[\"files\"], audio)\n",
246+
" if not context_status:\n",
247+
" for i in range(len(context)):\n",
248+
" time.sleep(0.1)\n",
249+
" yield \"Atom\\n\" + context[: i+1]\n",
250+
" else:\n",
251+
" question = message[\"text\"]\n",
252+
" \n",
253+
" Prompt = generate_prompt(context, question)\n",
254+
"\n",
255+
" if Prompt == \"\":\n",
256+
" error = \"Error : Empty input sent!\"\n",
257+
" for i in range(len(error)):\n",
258+
" time.sleep(0.1)\n",
259+
" yield \"Atom\\n\" + error[: i+1]\n",
260+
" else:\n",
261+
" # print(Prompt) #test\n",
262+
" \n",
263+
" if len(history) == 0:\n",
264+
" ephemeral_chat_history.clear()\n",
265+
"\n",
266+
" ephemeral_chat_history.add_user_message(Prompt)\n",
267+
"\n",
268+
" reply = chain.invoke({\"messages\":ephemeral_chat_history.messages})\n",
269+
"\n",
270+
" ephemeral_chat_history.add_ai_message(reply)\n",
271+
"\n",
272+
" for i in range(len(reply)):\n",
273+
" time.sleep(0.1)\n",
274+
" yield \"Atom\\n\" + reply[: i+1]"
275+
]
276+
},
277+
{
278+
"cell_type": "markdown",
279+
"metadata": {},
280+
"source": [
281+
"# Create chatbot UI using Gradio"
282+
]
283+
},
284+
{
285+
"cell_type": "code",
286+
"execution_count": 48,
287+
"metadata": {},
288+
"outputs": [
289+
{
290+
"name": "stdout",
291+
"output_type": "stream",
292+
"text": [
293+
"Running on local URL: http://127.0.0.1:7871\n",
294+
"\n",
295+
"To create a public link, set `share=True` in `launch()`.\n"
296+
]
297+
},
298+
{
299+
"data": {
300+
"text/html": [
301+
"<div><iframe src=\"http://127.0.0.1:7871/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
302+
],
303+
"text/plain": [
304+
"<IPython.core.display.HTML object>"
305+
]
306+
},
307+
"metadata": {},
308+
"output_type": "display_data"
309+
},
310+
{
311+
"data": {
312+
"text/plain": []
313+
},
314+
"execution_count": 48,
315+
"metadata": {},
316+
"output_type": "execute_result"
317+
}
318+
],
319+
"source": [
320+
"input_audio = gr.Audio(\n",
321+
" sources=[\"microphone\"],\n",
322+
" type=\"filepath\",\n",
323+
" label=\"Audio\",\n",
324+
" waveform_options = gr.WaveformOptions(\n",
325+
" waveform_color=\"#01C6FF\",\n",
326+
" waveform_progress_color=\"#0066B4\",\n",
327+
" skip_length=2,\n",
328+
" show_controls=False,\n",
329+
" ),\n",
330+
")\n",
331+
"\n",
332+
"gr.ChatInterface(\n",
333+
" slow_reply,\n",
334+
" multimodal=True,\n",
335+
" additional_inputs = input_audio,\n",
336+
" undo_btn=None,\n",
337+
" title=\"MultiInputChatbot\",\n",
338+
" description=\"Your all-in-one multilingual assistant for text, audio, and file-based conversations.\"\n",
339+
").launch()"
340+
]
341+
}
342+
],
343+
"metadata": {
344+
"kernelspec": {
345+
"display_name": "Python 3",
346+
"language": "python",
347+
"name": "python3"
348+
},
349+
"language_info": {
350+
"codemirror_mode": {
351+
"name": "ipython",
352+
"version": 3
353+
},
354+
"file_extension": ".py",
355+
"mimetype": "text/x-python",
356+
"name": "python",
357+
"nbconvert_exporter": "python",
358+
"pygments_lexer": "ipython3",
359+
"version": "3.11.3"
360+
}
361+
},
362+
"nbformat": 4,
363+
"nbformat_minor": 2
364+
}

0 commit comments

Comments
 (0)