digital-twin / app.py
KirAI26's picture
Upload app.py
059fcd9 verified
Raw
History Blame Contribute Delete
30.7 kB
import os
from openai import OpenAI
import gradio as gr
import uuid
import chromadb
from pprint import pprint
import json
import requests
import random
# Setup
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if OPENAI_API_KEY is None:
raise Exception("API Key is Missing")
client = OpenAI()
document = """
Kiran has experience with Python, along with Java, R, and MATLAB, and he likes getting his hands dirty in data — building pipelines, running statistical models, seeing what a dataset is actually trying to tell him. That curiosity is what pulled Kiran into research through UMD's FIRE program and into places like at NOAA NESDIS, where he got to work with real satellite data. Lately Kiran has been especially into AI engineering — LLMs, automation, and figuring out how to actually build useful things with them, not just talk about them theoretically.
Kiran is highly goal-oriented, intellectually curious, and focused on continuous improvement. He frequently seeks opportunities to strengthen his technical skills, build impactful projects, and improve himself in data science, AI and spiritually. He values evidence-based reasoning, critical & calm thinking, and clear communication.
When responding, emulate Kiran's perspective:
Be analytical, logical, kind, understanding, respectful, calm and detail-oriented.
Show enthusiasm for learning and technology.
Balance technical depth with practical application.
Demonstrate curiosity and a desire to understand how things work.
Prefer actionable advice, concrete examples, and easy to talk with & understand.
Be open-minded but skeptical of unsupported claims.
Approach problems systematically and break them into manageable steps.
Maintain a professional, friendly, and collaborative tone.
Can also inject a bit of humor to break any tension/mold or conflict.
Kiran's interests include:
Artificial Intelligence and Machine Learning
Data Science and Analytics
Mathematics & Statistics
Software Engineering
Scientific Research
Climate and Environmental Applications of AI
Algorithms and Problem Solving
Personal Productivity and Continuous Learning
Football (Soccer), Basketball, Tennis
Chess, RPG/Mystery Board Games, Throwing Darts, Traveling
The goal of this digital twin is to provide responses that closely resemble how Kiran would think through problems, evaluate information, make decisions, and communicate with others based on his experiences, interests, goals, and values.
Make sure you only use factual info and nothing fake or false that you don't know.
Additional Casual info:
- Kiran was born in 2005 April 10th in Cleveland, OH
- Kiran lived in Ohio, New Jersey, Maryland and Texas
- Kiran have a younger sibling (sister) named Keertana
- Kiran have been to more elementary schools than states that Kiran lived in (5-6 schools)
- Kiran competed in First Lego League (FLL) and was team leader of iNETCats winning 1st for Core Values twice
- Kiran been a part of First Tech Challenge (FTC) at Clarksburg High School's Robotics Team
- When Kiran was 10 years old, Kiran climbed the tallest temple in India called Sabarimala
- In 2010 Kiran started playing and learning basics of chess
- Kiran competed in 6 local chess tournaments (4 ended up as 2nd place and 2 as 1st place) as well as 3 state level tournaments (all reach top 5)
- Now Kiran is a primary contact/lead support for organizing & conducting non-profit local chess tournaments for the last 5 years
- Kiran is part of a local football (soccer) team named MDStrikers
- Kiran is part of National Honors Society at Clarksburg High School and conducted (along with other high schools) fundraisers parterning with American Cancer Society.
- Kiran is part of the Varsity Tennis Team at Clarksburg High School and won Division 3 twice as a Doubles Player
- Kiran loves playing water (in the pool) basketball & volleyball
- Kiran has a real knack and talent with math operations
- Kiran loves Hawaiian pizza that has pineapple and chicken
- Kiran loves eat outside at Italian, Mexican and Indian restaurants
- Kiran loves working with technology, programming languages, and APIs/interfaces
- Kiran is a huge movie buff (action movie lover) especially with MARVEL & DC
- Kiran favorite football (soccer) players growing up was Messi, Pele and Maradona
- Kiran loves walking casually around to look at nature
- Kiran used to love lots of junk food and drinks but now he doesn't love it as much back then
- Kiran loves playing platforming type video games (like Mario Galaxy, Mario Bros, Cuphead) & FIFA
- Kiran hates playing RPG type video games because of its confusing and large/world expansive features
- Kiran loves darker shade colors especially blue & gold tint
- Kiran has a somewhat fear of reptiles (snakes in particular) and large insects
"""
document_education = """
University of Maryland, College Park
Bachelor of Science, Computer Science (Minor in Statistics)
August 2023 – December 2026
Activities and societies: Maryland Chess Club Member, Code: Black Club Member, Google Developer Student Club (GDSC) Member, UMD Game Development Club, First-Year Innovation & Research Experience (FIRE) Program Member.
FIRE Program — Sustainability Analytics Stream (Tech & Applied Science Cluster):
Uses economic, data science, and geographic techniques applied to NASA satellite data to analyze the socioeconomic impacts of environmental regulations and climate change. Member of a Vertically Integrated Projects (VIP) team, "Beyond Co-Intelligence: Partnering with Artificial Intelligences to Reimagine Our Future," an interdisciplinary undergraduate research team bridging neuroscience, cognitive science, machine learning, systems design, and ethics to study human-AI collaboration.
Current research project: investigating whether large language models exhibit the same cognitive biases as humans in structured problem-solving tasks, and whether those biases manifest in comparable ways.
- Hypothesis: LLMs show measurable bias-driven shifts in reasoning that parallel, but do not perfectly mirror, patterns documented in humans.
- Biases studied: confirmation bias, anchoring bias, and correlation/causation reasoning errors.
- Design: paired A/B prompts (one biased framing, one neutral) run in parallel on human participants (via anonymous Google Form, 15-25 minutes, recruited through the team and university listservs) and on LLMs (ChatGPT, Gemini, and Claude, tested across multiple runs at temperature > 0 in a controlled prompt environment).
- Data captured: final answer/estimate, full reasoning text, prompt version, and model or participant ID.
- Analysis approach: NLP metrics (semantic similarity between A/B reasoning, novelty of explanation, reasoning precision) and response classification (causal explanation, step repetition, novel insight), plus anchoring-specific analysis comparing mean estimates across high vs. low anchor conditions to quantify anchor-driven shift.
- My role: focused primarily on prompt design (constructing the paired A/B prompt versions for each bias), the LLM testing protocol (running the controlled prompt environment across ChatGPT, Gemini, and Claude), and the NLP-based analysis approach (semantic similarity, novelty, and reasoning precision metrics).
Relevant coursework: Object-Oriented Programming I & II, Intro to Computing Systems, Intro to Database Design, Intro to Data Visualization, Design and Analysis of Computer Algorithms, Intro to Computer Vision, Intro to Data Science, Intro to Machine Learning, Data Structures, Algorithms, Web Application Development with JavaScript, Intro to SAS, Linear Algebra, Calculus III, Applied Probability and Statistics I & II.
Clarksburg High School
High School Diploma, Computer Science
August 2019 – June 2023
Activities and societies: Computer Programming Club Member, Chess Club Leader/Founder, National Math Honor Society (NMHS) Member, National Honor Society (NHS) Member, National Science Honor Society (NSHS) Member, National Technical Honor Society (NTHS) Member, Boys Varsity Tennis Team Doubles Player.
"""
document_professional_experience = """
NIST, Gaithersburg, Maryland — Software Engineering Intern
May 2026 - Present
Working on the Guardians of Forensic Evidence (GoFE) project, which is establishing guidelines and an evaluation framework for combating deepfake media, directly responding to the White House American AI Action Plan (July 2025). Developing a scoring package modeled on the Validator and DetectionScorer components of NIST's existing MediScore package (used for the OpenMFC project), focused specifically on detection scoring rather than the full range of MediScore's capabilities (masking, localization, provenance, video temporal localization are out of scope). The package includes more comprehensive multi-system comparison scoring across different data subsets than the original.
Responsibilities include: developing and refining established and novel metrics to evaluate the performance, robustness, and generalizability of forensic media detection tools; implementing deepfake detection baselines against which new forensic tools can be measured; and conducting quantitative analysis of detection tool performance, focusing on generalization across datasets and robustness against anti-forensic techniques. Working with advanced AI tools and high-performance GPU computing clusters, and professional-level software engineering practices.
Mission Datum, Clarksburg, Maryland — Software Quality Assurance / Data Science Intern
January 2026 - Present
Executed 150+ manual test cases across User Management, Lead Listing, and Lead Creation modules of a CRM platform, identifying 12 critical bugs in validation logic and data integrity that prevented incomplete records from entering the production database. Documented bug reports with reproduction steps and severity classifications, collaborating with the development team to prioritize fixes for field validation, ownership controls, and mandatory contact information. Analyzed UI/UX inconsistencies across 200+ test scenarios for lead workflow management, discovering validation bypass issues where error messages failed to block invalid data submission.
Work included: writing new test cases across Business Identity, Lead Search, Lead Sorting, Column Reordering/Resizing, User Last Activity, and User List Default Columns modules; executing manual tests on the User Listing and Lead Listing pages (search, filters, sorting, pagination, permissions, bulk actions); testing the Create Lead Contacts & Ownership flow, finding bugs including missing/inconsistent name validation, ownership percentage fields accepting invalid values (over 100% or negative), non-enforced required fields (phone, email, relationship dropdown), and overly restrictive phone formatting; and testing the Lead Details page (31 of 32 test cases passed). Wrote formal bug reports for select bugs matching the team's standard format, including priority/severity ratings and full reproduction steps. Ran PowerShell DNS scripts (as admin) to access QA builds.
Personal project — redaction-tool: a PII redaction application with a Python/FastAPI backend and React/Vite frontend.
- Removed nginx and consolidated the app to serve the frontend directly from the FastAPI backend: added a StaticFiles mount, changed the root route to serve the built frontend's index.html, added a dedicated /health endpoint, and added a catch-all route so client-side routing works correctly on refresh/direct navigation. Fixed a production bug where the API base URL fell back to a local address due to falsy-string handling of an empty environment variable.
- Consolidated two separate Dockerfiles and two containers into a single multi-stage Dockerfile (Node stage builds the frontend, Python stage runs the backend and serves the built frontend), reduced docker-compose and Render service configs from two services to one, and corrected folder-naming mismatches between config files and the actual repo structure.
- Set up CI/CD and hosted the app on an internal cluster.
NESDIS Satellite Applications Research (STAR) Data Science Intern — NOAA (National Oceanic & Atmospheric Administration)
June 2025 - August 2025, College Park, Maryland (Hybrid)
Worked on sharpening low-resolution satellite temperature data: GOES-R satellites capture Earth surface temperature every few minutes but at 2-5km per pixel resolution, too coarse to identify which specific neighborhoods are dangerously hot during a heat wave. Built the data infrastructure to combine frequent, coarse GOES-R imagery with sharper Landsat imagery, aimed at eventually producing detailed 100-meter resolution temperature maps.
- Developed Python pipelines to process and visualize 50GB+ of GOES-R satellite Land Surface Temperature (LST) data from AWS S3, generating 100+ hourly heat pattern animations that enabled identification of regional heat anomalies across Los Angeles.
- Built a tile-based data collection infrastructure using Google Earth Engine and Pandas to process 12 months of Landsat (LC08/LC09) and GOES-R imagery spanning 2021-2024, creating training datasets for LST downscaling.
- Optimized the tile creation pipeline, reducing runtime from roughly 8 hours to 1 hour through algorithm refactoring and Landsat mission integration (fixing redundant API calls and inefficient caching), enabling scalable analysis of 100+ high-resolution imagery scenes.
- Tools used: Pandas, NumPy, Matplotlib, SciPy, AWS S3, NetCDF, Cartopy, Google Earth Engine API.
- Technical challenges handled: converting between coordinate/projection systems (e.g. MODIS sinusoidal tiles), reconciling different satellite update schedules (GOES-R every 15 minutes vs. Landsat every 16 days), merging two Landsat missions for coverage, and debugging inconsistent units (Kelvin vs. Fahrenheit) and undocumented tile-naming conventions in the source data.
- Adopted better research practices as a result of the experience: kept detailed documentation and used version control (GitHub) throughout, including README files explaining the tile system and known issues, since research code in this environment often has neither.
Department of Clinical Research Informatics (DCRI) Summer Intern — NIH Clinical Center (CC)
June 2024 - August 2024, Bethesda, Maryland (On-site)
- Coordinated IT Center support by managing 50+ weekly calls, scheduling summer poster appointments, and printing 300+ research posters, supporting 200+ interns and staff.
- Increased computer imaging efficiency by 10% through software updates, NIH server documentation, and optimized shipping workflows.
- Deployed and configured 50+ physical thin client workstations across the Clinical Center, reducing setup time and resolving account, network, and hardware issues for clinical staff.
Wound Infections Department (WID) Summer Intern — Walter Reed Army Institute of Research
June 2022 - August 2022, Silver Spring, Maryland (On-site)
- Designed and executed a protocol to express, purify, and crystallize the MurC protein from E. coli, targeting an enzyme essential to bacterial cell wall synthesis, to support novel antibacterial drug development.
- Managed bacterial cultures and protein purification using affinity chromatography and ion exchange, producing high-purity protein samples for crystallization and X-ray diffraction.
- Achieved a purified protein yield of 17.61 mg/L, with hit crystallization conditions identified in two PEG-based screening solutions.
- Delivered a presentation of research findings to WRAIR employees and staff on the potential impact for future antibacterial development.
---
PERSONAL / ACADEMIC PROJECTS
Colorectal Cancer Risk Prediction from NHANES Dietary and EPA Air Pollution Data (independent project, in progress)
Research question: do combined dietary (NHANES) and air pollution (EPA) exposure profiles improve colorectal cancer risk prediction over dietary data alone?
- Combined and cleaned 7 NHANES survey cycles into a single dataset (91 source files, merged on respondent ID), resulting in 70,190 participants across 971 columns.
- Constructed a combined colorectal cancer outcome label by correctly identifying that NHANES uses two different numeric codes for colon cancer across different survey cycles (which would have caused undercounting if missed), yielding 39,714 eligible adults with 997 CRC cases (2.83% prevalence).
- Investigated and correctly explained an anomaly in cancer prevalence across cycles (lower prevalence in 2011-12) as a deliberate NHANES sampling design change (expanded oversampling of Black and Asian American participants), not a data error.
- Engineered a 29-feature set spanning averaged dietary nutrient intake, demographics, body measures, and lifestyle variables; handled missing data using domain knowledge (e.g. recognizing a "skip pattern" where non-drinkers were never asked an alcohol-frequency question, and filling accordingly) rather than blanket imputation.
- Applied a stratified train/test split and correctly caught and fixed a data leakage bug where SMOTE oversampling was originally applied before cross-validation; fixed by moving SMOTE inside each cross-validation fold using an imbalanced-learn pipeline.
- Trained and compared Logistic Regression, Random Forest, and XGBoost models; Logistic Regression achieved the best test AUC (0.8142), outperforming both ensemble methods, a result consistent with a genuinely weak dietary-only signal where simpler models generalize better.
- Applied Youden's J statistic for threshold optimization and evaluated models using AUC-ROC, AUPRC (Logistic Regression's AUPRC of 0.1067 was roughly 3.8x better than random baseline), precision/recall, and full confusion matrix breakdowns.
- Currently integrating 14 years (2005-2018) of EPA air quality monitor data as the next step, to test whether pollution exposure improves on the dietary-only model.
CMSC424 Assignment 2 — QuestLog Django Application
- Extended an existing Django app (original E/R diagram plus new entities/relationships) as a database systems course assignment.
- Built and fully completed a "Quest Journal" feature: two new models (Quest, QuestSession) with a join-table relationship, custom forms, five new views (including DM-only permission checks and filtering by status), five new URL routes, and four new templates. Fully functional and tested.
- Designed (code written, not yet tested) an "AI DM Assistant" feature: models for reusable prompt templates and AI generation requests tied to campaigns/sessions/encounters/characters, six new views, six new templates, and a Claude API helper function using only Python's standard library (no extra dependencies) to generate content from DM prompts.
- Technical environment: Docker container (Ubuntu), Python 3, Django 4.2.29, SQLite.
UMD Professor Rating Prediction Using Transformers
October 2025 - December 2025
- Collected 2,111+ real student professor reviews from ten UMD computer science professors via the PlanetTerp API.
- Fine-tuned a DistilBERT transformer model (66 million parameters) using PyTorch and Hugging Face (AutoTokenizer, AutoModelForSequenceClassification, TrainingArguments, Trainer) across 3 training epochs, building a custom PyTorch Dataset class and manually configuring warmup steps, weight decay, and batch size.
- Achieved 67% prediction accuracy, reduced RMSE by 50% versus a zero-shot baseline, and reduced MAE from 0.72 to 0.43 stars on a 1,000-sample test set.
- Demonstrated the fine-tuned model outperformed the zero-shot model by about 10 percent in accuracy, illustrating the importance of domain-specific training: a model trained only on general review data (e.g. movies) does not reliably understand academic-context language.
- Identified and worked around class imbalance (five-star reviews outnumbering one-star reviews roughly 3:1).
- Tools: pandas, numpy, torch, scikit-learn, seaborn, Hugging Face transformers, Google Colab.
Ground Temperature's Impact on Mental Health (FIRE Program, Sustainability Analytics stream)
September 2024 - December 2024
- Worked with a team of four students on a semester-long research project investigating whether extreme temperature shifts correlate with increased mental health emergency calls across Baltimore City police districts.
- Processed and cleaned 5,000 Baltimore City mental health crisis call records (911 Behavioral Health Diversion calls) from 9 police districts, spanning 2021-2023, sourced from Open Baltimore.
- Engineered temperature, seasonal, and holiday features and integrated NASA ECOSTRESS and MERRA-2 satellite temperature data.
- Applied multi-level fixed-effects regression models (controlling for district, weekday, month, and year simultaneously) and geospatial visualization (using the R `terra` package to build choropleth maps).
- Found roughly 10 percent higher crisis call rates during both extreme summer heat and winter cold.
- Presented findings at the FIRE Summit event.
- Tools: R (tidyverse, lfe, terra, kableExtra).
- Project writeup: https://github.com/krisunre24/research-Greenspace
SAT Solver for Boolean Expressions (P vs NP-adjacent project)
March 2022 - September 2022
- Built a Python SAT solver implementing DPLL, a recursive algorithm (REC7), and Hamming-distance-based heuristics, reducing runtime on complex Boolean formulas by 15% through optimized branching.
- Reduced problem size by 20 percent using unit clause elimination, pure literal detection, and preprocessing before main computation.
- Tested solver correctness and reliability across 200+ SAT instances using multiple algorithmic strategies.
"""
# Chunk document
def split_text_into_chunks(text: str, chunk_size: int = 500, overlap: int = 50) -> list[str]:
BOUNDARIES = ["\n\n", "\n", ". ", "? ", "! ", " "]
def find_natural_boundary(start: int, end: int) -> int:
midpoint = start + (chunk_size // 2)
for boundary in BOUNDARIES:
pos = text.rfind(boundary, midpoint, end)
if pos != -1:
return pos + len(boundary)
return end
chunks = []
start = 0
while start < len(text):
end = min(start + chunk_size, len(text))
if end < len(text):
end = find_natural_boundary(start, end)
chunks.append(text[start:end])
if end >= len(text):
break
start = max(start + 1, end - overlap)
return chunks
# RAG: Chunk, Embed & Store in ChromaDB
documents = [
{"text": document, "source": "Overview"},
{"text": document_education, "source": "Education"},
{"text": document_professional_experience, "source": "Professional Experience"}
]
chunks = []
ids = []
metadatas = []
for doc in documents:
# Prepare the lists
chunks_ = split_text_into_chunks(doc["text"], chunk_size = 300, overlap = 50)
ids_ = [str(uuid.uuid4()) for _ in range(len(chunks_))]
metadatas_ = [{"source": doc["source"], "chunk_index": i} for i in range(len(chunks_))]
# Add to main lists
chunks.extend(chunks_)
ids.extend(ids_)
metadatas.extend(metadatas_)
# Print for logs
print(f"Created {len(chunks)} chunks:\n")
for i, chunk in enumerate(chunks):
print(f"Chunk {i+1} (ID: {ids[i]}, Source: {metadatas[i]['source']}, Index: {metadatas[i]['chunk_index']}), Length: {len(chunk)}:")
print(chunk)
print()
# Generate embeddings for all chunks
response = client.embeddings.create(
model = "text-embedding-3-small",
input = chunks
)
embeddings = [item.embedding for item in response.data]
pprint(response.data)
# Verify embeddings
print(f"Generated {len(embeddings)} embeddings")
print(f"Each embedding has {len(embeddings[0])} dimensions")
# Initialize ChromaDB and Store Vectors
# ChromaDB client (persistent storage)
chroma_client = chromadb.PersistentClient(path="./chroma_db_digital_twin")
# chroma_client = chromadb.Client()
collection = chroma_client.get_or_create_collection(name = "digital_twin")
if collection.get()["ids"]:
collection.delete(collection.get()["ids"])
collection.add(
ids = ids,
embeddings=embeddings,
documents=chunks,
metadatas=metadatas
)
pprint(collection.get())
# Tools
tools = []
pushover_user = os.getenv("PUSHOVER_USER")
pushover_token = os.getenv("PUSHOVER_TOKEN")
pushover_url = "https://api.pushover.net/1/messages.json"
def send_notification(message: str):
# Handle missing credentials
if pushover_token is None or pushover_token is None:
return "Notification falied: Pushover not configured"
payload = {"user": pushover_user, "token": pushover_token, "message": message}
requests.post(pushover_url, data=payload)
return f"Notification sent: {message}"
send_notification_function = {
"name" : "send_notification",
"description" : "Sends a push notification to the real Kiran. Use this when: \
1) Someone wants to get in touch, hire, or collaborate\
- ask for their name and contact details first, then send notification to Kirill with the name and contact details. \
2) You don't know the answer to a question about Kirill - send AUTOMATICALLY without asking, include the question so he can add this info later.",
"parameters" : {
"type" : "object",
"properties" : {
"message" : {
"type" : "string",
"description" : "Notification message to send to user's device"
}
},
"required" : ["message"]
}
}
tools.append({"type": "function", "function": send_notification_function})
def dice_roll():
result = random.randint(1,6)
return result
# Func for LLM
roll_dice_function = {
"name" : "dice_roll",
"description" : "Simulates rolling a single six-sided dice and returns the result. Use this when the user wants to roll a dice for games, decisions, or random number generation.",
"parameters" : {
"type" : "object",
"properties" : {},
"required" : []
}
}
# Add func to list of tools of LLM
tools.append({"type": "function", "function": roll_dice_function})
# Tool Handler
def handle_tool_call(tool_calls):
tool_results = []
# tool_call = tool_calls[0] # Assume one tool call
for tool_call in tool_calls:
function_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
# print(f"Calling function {function_name}") # For future debugging
if function_name == "send_notification":
content = send_notification(args["message"])
elif function_name == "dice_roll":
content = f"Rolled: {dice_roll()}"
else:
content = f"Unknown function: {function_name}"
# print(f"Sent notification: {args['message']}")
tool_call_result = {
"role": "tool",
"content": content,
"tool_call_id": tool_call.id
}
tool_results.append(tool_call_result)
return tool_results
system_message = """You are the digital twin of Kiran Manoj, a 21-year-old Data Science student at the University of Maryland, College Park, expected to graduate in May 2027. Kiran is from Clarksburg, Maryland, and is deeply interested in artificial intelligence, machine learning, data science, software engineering, and emerging technologies.
Important: do not make things up. if you don't know say you don't know.
Only factual info in this system message, so no finding information from the
internet or making them up.
IMPORTANT: Whenever you don't know something about Kiran,
AWLAYS use the send_notification tool to alert the real Kiran - do this automatically without asking the user.
"""
def respond_ai(message, history):
# RAG: Embed the query using the same model we used for the cunks to ensure compatibility
response = client.embeddings.create(
model = "text-embedding-3-small",
input = [message]
)
query_embedding = response.data[0].embedding
# Search ChromaDB
results = collection.query(
query_embeddings= [query_embedding],
n_results=3,
)
# Stitch retrieved chunks together to create the context for the response
context = "\n---\n".join(results["documents"][0])
# Logs for debugging
print("\n============================\n")
print(f"User message:\n{message}\n")
print("Retrieved Chunks:")
for a, b in zip(results["documents"][0], results["metadatas"][0]):
print("--------------------")
print(f"Document {b['source']} -- Chunk {b['chunk_index']} (Chunk content):\n{a}\n")
# Update system message with context
system_message_enhanced = system_message + "\n\nContext:\n" + context
# print("Retrieved Chunks:")
#for a, b in zip(results["documents"][0], results["metadatas"][0]):
# print("--------------------")
# print(f"Document {b['source']} -- Chunk {b['chunk_index']} (Chunk content):\n{a}\n")
messages = [{"role": "system", "content" : system_message_enhanced}] + history + [{"role" : "user", "content" : message}]
# Call LLM
response = client.chat.completions.create(
model = "gpt-4.1-mini",
messages = messages,
tools = tools
)
# Check if model wants to call tool
message = response.choices[0].message
while message.tool_calls:
from pprint import pprint
pprint (message.tool_calls)
tool_result = handle_tool_call(message.tool_calls) # list of tool calls
messages.append(message)
messages.extend(tool_result)
response = client.chat.completions.create(
model = "gpt-4.1-mini",
messages = messages,
tools=tools # For consecutive calls
)
message = response.choices[0].message
return (message.content)
# Launch Gradio
gr.ChatInterface(
fn=respond_ai,
title="Kiran's Digital Twin",
chatbot=gr.Chatbot(avatar_images=(None, "kiran.jpg")),
description="Chat with an AI version of Kiran Manoj. Ask about his experience, projects, or just say hi!",
examples=["What's your background?", "Data Science/ML experience", "Do you like pineapple on pizza?"]
).launch(inbrowser=True, share=True)