# ------------------------------------------------------------------ # Workaround for Starlette expecting query_string as bytes # ------------------------------------------------------------------ import starlette.datastructures as _sd _original_init = _sd.URL.__init__ def _patched_init(self, url="", scope=None, **kwargs): if scope is not None: scope = dict(scope) qs = scope.get("query_string") if isinstance(qs, str): scope["query_string"] = qs.encode("latin-1") return _original_init(self, url=url, scope=scope, **kwargs) _sd.URL.__init__ = _patched_init # ------------------------------------------------------------------ # Gradio app # ------------------------------------------------------------------ import os from openai import OpenAI import gradio as gr from langchain_text_splitters import CharacterTextSplitter import uuid import chromadb from pprint import pprint import json import random import requests #------------------------------------------------ # SET UP #------------------------------------------------ open_api_key = os.getenv('OPENAI_API_KEY') if open_api_key is None: raise Exception("API Key is missing!") client = OpenAI() #------------------------------------------------ # Document #------------------------------------------------ document_overview = ''' Karthik has 25 years of experience in the software Industry. Currently he is out of work and actively looking for one. He has lot of interest in Indian classical music and likes Singing and playing musical instrument called Harmonium. ''' document_education = ''' Visvesvaraya National Institute of Technology (VNIT), Nagpur, India Bachelor of Engineering Electrical Engineering ''' document_professional_experience = ''' Principal Engineer Oracle · Full-time Start Date: Jan 2011 End Date: Mar 2026 · 15 yrs 3 mos San Francisco Bay Area As a Member of Oracle Integration Cloud Team, I was responsible for the following - Fleet Operations & Patching: Orchestrated end-to-end monthly and quarterly patch management for 25%+ of the global Oracle Integration Cloud Gen 2 (OICG2) fleet and 50%+ of Gen 1 (OICG1) customers, ensuring stable, reliable regional updates. Large-Scale Migrations: Spearheaded the successful migration of 300+ enterprise customer instances from OICG1 to OICG2; enhanced legacy transition tooling to streamline upgrade planning for rapid response and support teams. Data Analytics & Observability: Served as Lead Developer for OIC service dashboards using Oracle Analytics Cloud (OAC) and Autonomous Transaction Processing (ATP), providing leadership with critical long-term visibility into customer usage and instance migration metrics for future capacity planning. DevOps & SLA Automation: Executed mission-critical DevOps operations to resolve high-priority production incidents within strict SLAs; proactively automated provisioning processes and designed infrastructure tools to close operational gaps for upcoming OICG3 architectures Goldman Sachs logo Senior Analyst, Credit Risk Technology Goldman Sachs · Full-time Start Date:May 2010 - End Date:Jan 2011 · 9 mos Software/ Technologies – Sybase, Ant, Java, and in-house web framework based, custom cache infrastructure. * Work with “Credit Risk” data sourcing team and implement “trade reconciliation” requirement mandated by US fed. * Enhance & migrate the in-house web framework to the newer version of JavaScript client library. * Work with the build infrastructure team to improve overall build performance. * Mentor new hires. Etrade Financial logo Consulting Architect Etrade Financial Start Date:Feb 2008 - End Date:Apr 2010 · 2 yrs 3 mos Responsibility: Enhance the home grown high volume custom Java Web Application Framework. Technologies: Java, Strut2, Spring3, Javascript, jQuery, Maven, Tomcat 6 * Support, enhance the framework based on requests from internal teams that employ the Application Framework. * Lead the effort to determine the open source framework that fits the company requirements. This involved researching all leading Java Web Application frameworks like Struts2, Spring MVC, JSF, Wicket etc., * preparing detailed analysis report and recommending the framework of choice. * Developed Maven Archetype and plugins for the Application framework to enable new hires jump start development * E*TRADE point of contact for all Spring application development support with Spring Source (VMWare) Added ability to execute Spring 3.0 MVC artifacts from within the homegrown Framework runtime to allow seamless “future” integration. * Integrate Siteminder 6.0 java agent for easy authentication. * Play a lead role in the analysis of Rich Web Client Framework. * Integrated Spring framework with the existing Web Framework ''' #------------------------------------------------ # System Message #------------------------------------------------ system_message = ''' You are a digital twin of person named Karthik Gurumurthy that answers questions based on the available context. if you dont know the answer, say you dont know. Do NOT make things up. Use all the information made avaible to you through the context to provide the best answer possible. Stick to the context that you are being provided while framing a response. IMPORTANT: Whenever you dont have an information about real Karthik, send a notification to the real Karthik using the 'send_notification' tool automatically WITHOUT notifiying the user about this notification ''' #------------------------------------------------ # Chunk The Document #------------------------------------------------ #------------------------------------------------ # RAG Chunk, Embed and Store in ChromaDB #------------------------------------------------ documents = [ {'text':document_overview, 'source' : 'Overview'}, {'text':document_professional_experience, 'source' : 'Professional Experience'}, {'text':document_education, 'source' : 'Education'} ] splitter = CharacterTextSplitter( separator="", chunk_size=250, chunk_overlap=20 ) chunks = [] ids = [] metadatas = [] for doc in documents: chunks_ =splitter.split_text(doc['text']) ids_ = [str(uuid.uuid4()) for _ in range(len(chunks_))] metadatas_= [{"source":doc['source'],"chunk_index":i} for i in range(len(chunks_))] chunks.extend(chunks_) ids.extend(ids_) metadatas.extend(metadatas_) print(len(chunks)) response = client.embeddings.create( model = "text-embedding-3-small", input = chunks ) embeddings = [item.embedding for item in response.data] #Verify Embeddings print(f"Generated {len(embeddings)} embeddding and each embedding has {len(embeddings[0])} dimensions") chroma_client = chromadb.PersistentClient(path="./chroma_MULTI_db") collection = chroma_client.get_or_create_collection("digital_twin") coll_data = collection.get() if coll_data["ids"]: collection.delete(coll_data["ids"]) collection.add( ids=ids, embeddings=embeddings, documents=chunks, metadatas=metadatas ) pprint(collection.get()) #------------------------------------------------ # Tools #------------------------------------------------ pushover_user = os.getenv('PUSHOVER_USER') pushover_token = os.getenv('PUSHOVER_TOKEN') print(pushover_user) print(pushover_token) pushover_url = "https://api.pushover.net/1/messages.json" def send_notification(message:str): payload = {"user":pushover_user,"token":pushover_token,"message":message} requests.post(pushover_url,data=payload) return message send_notification_function = { "name" : "send_notification", "description" : "push notification to users phone via Pushover. use this alert the user", "parameters" : { "type": "object", "properties": { "message": { "type": "string", "description": "The notification alert message to the user" } }, "required": ["message"] } } def dice_rool(): return random.randint(0,6) dice_roll_function = { "name" : "dice_rool", "description" : "simulates rolling a single 6 sided dice and returns the result. Use it when the user wants to roll a dice for a game , decision or generate a random number ", "parameters" : { "type": "object", "properties": {}, "required": [] } } tools = [{"type":"function","function":send_notification_function}, {"type":"function","function":dice_roll_function}] #------------------------------------------------ # Tools Handler #------------------------------------------------ def handle_tool_calls(tool_calls): tool_calls_results = [] for tool_call in tool_calls: fn_name = tool_call.function.name fn = globals()[fn_name] print (f"Got fn! {fn}") fn_args = json.loads(tool_call.function.arguments) if fn_args: fn_result = fn(**fn_args) else: print (f"Executing {fn}") fn_result = fn() print (f"Result {fn_result}") result = { "role":"tool", "tool_call_id": tool_call.id, "content":str(fn_result) } tool_calls_results.append(result) return tool_calls_results #------------------------------------------------ # Main Response Function #------------------------------------------------ def respond_ai(message,history): global system_message #RAG response = client.embeddings.create( model = "text-embedding-3-small", input = [message] ) query_embedding = response.data[0].embedding results = collection.query( query_embeddings=[query_embedding], n_results=5 , # Top 'k' closest matches to return include=["documents","metadatas"] ) context = "\n --- \n Context:\n".join(results["documents"][0]) #Logs for debugging print(f"*** RETREIVED Context **** for message ***** {message} ******") for a,b in zip(results["documents"][0],results["metadatas"][0]): print(f"<>\n{a}\n") system_message_enhanced = system_message + "\n\nContext:\n" + context messages = [{"role":"system","content":system_message_enhanced}] + history +[{'role': 'user', 'content': message}] print(messages) response = client.chat.completions.create( model="gpt-4.1-mini", messages = messages, tools = tools ) message = response.choices[0].message #check if Model wants to call tool while message.tool_calls: tool_result = handle_tool_calls(message.tool_calls) messages.append(message) messages.extend(tool_result) pprint (messages) response = client.chat.completions.create( model="gpt-4.1-mini", messages = messages, tools = tools ) message = response.choices[0].message return (message.content) #------------------------------------------------ # Launch Gradio #------------------------------------------------ gr.ChatInterface(fn=respond_ai).launch() openai gradio langchain_text_splitters chromadb requests