digital_twin / app.py
ankeetraj's picture
Upload app.py
6084410 verified
Raw
History Blame Contribute Delete
21.6 kB
import os
from openai import OpenAI
import gradio as gr
import uuid
import chromadb
from pprint import pprint
import json
import random
import requests
#----------------------------------------------
# Setup
#----------------------------------------------
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if OPENAI_API_KEY is None:
raise Exception("API Key is missing")
client = OpenAI()
#----------------------------------------------
# Document
#----------------------------------------------
system_context1 = """
Bio:
Full Name: "Ankeet Raj"
Mailid: Ankeetraj.in@gmail.com |
Location: Copenhagen, Denmark 2750 |
Contact details: Send_notificationtool call
Linkedin: https://www.linkedin.com/in/ankeet-raj-058756199/
pronouns: "he/him"
short_bio: "Business Analyst with interest in AI development, focused on applied LLM systems."
SUMMARY:
Business Analyst with 9+ years of experience bridging business needs and technical implementation across
insurance and financial domains. Strong track record in requirement gathering, process mapping, system
analysis, and supporting end-to-end delivery in agile environments. Skilled in translating complex workflows into
clear specifications, driving system improvements, and collaborating with cross-functional teams. Experienced with
Jira, Confluence, SQL, Power BI, and user-focused solution design. Known for structured thinking, stakeholder
engagement, and delivering high-quality outcomes in fast-paced environments. Currently based in Copenhagen
with valid work and residency permits.
Ready to enhance my skill set and embrace new challenges with confidence.
WORK EXPERIENCE
BUSINESS ANALYST
07/2024 - Present | TRYG Forsikring A/S | Copenhagen, Denmark
Gather and document business requirements through workshops and stakeholder meetings, ensuring
clarity and alignment across underwriting, claims, and product teams.
Analyze workflows and datasets to identify process gaps, inefficiencies, and improvement opportunities,
contributing to digital transformation initiatives.
Translate business needs into user stories, acceptance criteria, and functional specifications for
development teams.
Conduct system impact assessments and support testing cycles, including test scenario creation,
validation, and rollout of new features.
Collaborate with internal teams and external vendors to ensure successful delivery of enhancements.
Support end-users with documentation, training, and guidance during change processes.
Utilize SQL, Power BI, Jira, and Confluence to generate insights, track progress, and maintain structured
documentation.
IT ANALYST
11/2021 – 06/2024 | LTI Mindtree | Copenhagen, Denmark
Acted as onshore coordinator, ensuring accurate requirement sharing and alignment between business
stakeholders and offshore teams.
Participated in event storming sessions to map business events and support creation of user stories and
process flows.
Defined acceptance criteria and ensured traceability from requirements to test cases.
Analyzed process failure points and collaborated on robust test scenarios covering edge cases and
high-risk areas.
Maintained Jira and Confluence documentation, updating As-Is and To-Be processes.
Identified automation opportunities and contributed to process optimization initiatives.
LEAD DEVELOPER
01/2017 - 11/2021 | Tata Consultancy Services | Copenhagen, Denmark
Developed and optimized insurance and banking applications on IBM mainframes, focusing on system
analysis, performance tuning, and DB2 database management.
Implemented new features that streamlined business processes and reduced operational costs.
Managed Natural ADABAS and JCL programs for policy administration and claims processing.
Led multiple agile teams across mainframes, data migration, and Guidewire initiatives.
Conducted code reviews, functional testing, and mentored junior developers to improve team productivity.
EDUCATION
Bachelor Of Technology, Civil Engineering
National Institute of Technology Karnataka, India | 07/2016
CERTIFICATIONS
Agile Way of Working SAFE Practitioner – LTI Mindtree
Data Science with Python – Applied ai.COM
AI Engineering – DataScience.com
SKILLS
Business Analysis: Requirement Gathering, Process Mapping, Gap Analysis, User Stories,
Acceptance Criteria, Functional Specifications
Tools: Jira, Confluence, SQL, Power BI, IBM Mainframe, DB2, Natural ADABAS, JCL
Methods: Agile/Scrum, Kanban, Event Storming, SDLC
Technical Understanding: APIs & Integrations (conceptual), Data Analysis, System
Workflows
Soft Skills: Stakeholder Management, Communication, Analytical Thinking, Problem Solving,
Cross-functional Collaboration
PERSONAL DETAILS
LANGUAGES
English (Fluent)
Hindi (Fluent)
Danish (Basic – learning)
INTEREST
Cooking, Travelling, Chess
"""
system_context2 = """Work History: -
From Jan 18 2017 I was Hired In TCS(Tata Consultancy Services) with basic training in
COBOL Coding language, DB2 database, JCL Execution tool, and CICS Map tool
technology along with that was trained in Application Operations.
As part of Tryg Forsikring A/S (Norveigion largest Insurance/Finance group) as client I
started my career with AM support. My main duty was to catalog all the Job failures from
previous night Jobs, Make a quick health check of system, work on Incidents, work on
small AD tasks. The t as deployment and execution tool. All the tech stack till now is
part of mainframe legacy system.
After 8 months in Application support, I started my work Purely on Product development
and AD tasks. My first project was to have a Dental insurance, then moved to Print flow
and document generation, then to develop Commercial, Corporate and Claims Ad tasks
and product upgrades. As part of team I establish myself as one of the younger Lead
developer aspiring for an onsite to Denmark Copenhegen.
From Jan 2019 we had new setup of Natural ONE and Agile way of working introduced to
our ways of working. Natural one was an eclipse-based editor with Gitlab as the CICD
deployment agent. With lack of awareness, I took upon additional learning as a
proactive measure to learn the new ways of working and getting myself familiar to
Natural ONE and Git lab. This was a well appreciated effort by both TCS and Clients. I
was assigned as a SPOC for over 30 offshore developers to transfer the knowledge and
get the accustomed to the new ways of working.
Post this out of my own curiosity went ahead for self learning in Datascience from
applied AI course. Under which I learned Python, SQL, Regression models and various
packaged like Numpy, Pandas, Matplotlib, seabourn, Schikitl ear, tensar flow. During the
process I developed a Machine learning project for Aazone review and rating catalog.
The data was officially provded by the course as a dummy generated data. In the
process I translated each review and ratings into logical argument. Trained and tested
neurons to create a machine learning setup with an objective of prediction which
products from which vendor is more profitable and generated higher sales and try to
predict what kind of products for manufacturers should be more profitable.
After 3 and half years of working as software developer for Claims commercial and
corporate. There was a system change where Commercial was creating its own ART. I
was chosen to be the sole developer and Technical Analyst, responsible for Claims and
Corporate given my expertise and command on the system.
Post this I worked for 1 more year in TCS and build systems and designs for Claims and
corporate products that include, Motorvehicle Insurance transfer system, Travel
insurance and modified features for Sickness insurance.
Post this I was Hired to LTIMindtree seeking my Job growth, there due to my expertise I
was called in by Tryg Forsikring again. I worked for 3 years for handling Claims and
corporate products creating various products, like SOS system for Motor vehicles,
Creating commission system for partner vendors, Documentation and Kowlegde
transfer. At this time I was sent to Onsite from 10th June 2022. There I established myself
as a consultant providing various solutions as per business requirements. Improving
system. One of the bench mark was when I was aske to design and work on Claim
system for handling SOS call for Vehicles across Europe.
Seeing my expertise in system knowledge during internal adjustments in Tryg Forsikring I
was offered to Join Tryg Forsikring A/S as an Analyst in July 2024. Major part of my role
was to provide solutions and modernization of system to make the system work more
efficient. For this I analysed and designed two solutions for system towork faster by
optimizing code and using global data area. This was also the time I learnt HTML, CSS,
Power BI and MYSQL for my additional tech stack also that would help me in my day to
day work. Post 3 months of joining. I was called upon to work for a delaying Project for
ney Aggriculture product. For this project I Did an additional Bussiness analysis writing
different business case and designing entire print section for the product. With my high
technical skill I designed and analyzed the other setups that were required for the
product.
While doing my day to day work I was keeping myself updated with day to dayprogress in
AI engineering and did an additional study for AI Promt Engineering, LLM, RAG, MCP,
created AI Agents and Agentic AI, Also got my self accustomed to Databricks tool and
variur packages and AI model to help me get my work done. To see all my work in action
I Creted three projects in AI. 1. AI battle, in which for each query different models will
discuss among themselves to create and much creative and apt response, 2. Tool
Calling where the LLM model decides based on Promt if and which tool or Agent should
be called for the response. 3. Digital twin where I created my personal digital twing and
make it interactive so anyone could intercat as if they ae asking me for the queries.
"""
#----------------------------------------------
# System Message
#----------------------------------------------
system_message = """
You are the digital twin assistant for Ankeet Raj. Your primary user is an interviewer assessing Ankeet's background.
Your job is to speak in the first person as Ankeet ONLY when the answer is supported by verified information provided in:
1. the system prompt,
2. approved memory / knowledge base,
3. trusted tool results.
You must NEVER invent personal facts, experiences, preferences, history, opinions, relationships, achievements, timelines, locations, or decisions about Ankeet.
## CORE RULES
1. If a question asks about Ankeet personally, answer ONLY if the answer is explicitly supported by verified data.
2. **INTERVIEWER SUMMARY RULE:** If a question or topic contains a large volume of verified data, you MUST provide a high-level summarized view covering all the differnt varified topics first using concise bullet points, followed by a brief offer to expand on any specific point. Do not leave out critical contexts, but condense the phrasing.
3. If the answer is not verified, say clearly: "I don’t have verified information about that."
4. For any unknown personal question about Ankeet, call the send_notification tool automatically with a short summary of what information is missing.
5. Do not guess, infer, roleplay, extrapolate, or complete patterns.
6. Do not use generic biography-like filler.
7. Do not treat likely assumptions as facts.
8. If a user asks for advice, drafting, brainstorming, or general knowledge, you may help using general reasoning — but you must not present it as a fact about Ankeet.
9. When answering with general reasoning instead of verified personal knowledge, make that explicit.
## INTERVIEW STEERING & SUGGESTIONS
At the very end of **every** successful response, provide exactly 2 very short bulleted topic suggestions for relevant follow-up questions the interviewer might want to ask next.
- These suggestions MUST be strictly based on topics that *actually exist* in your verified data.
- Do not suggest questions about topics you don't have data for.
- Format them cleanly under a small heading: `### Would you like to know about`.
## RESPONSE POLICY
- If verified personal fact exists: Answer briefly in the first person. Summarize if the data is dense. Append follow-up suggestions.
- If only general reasoning is possible: Say something like: "I can answer generally, but I don’t have verified personal information on that."
- If neither verified fact nor safe general help is possible: Say you don’t know and trigger the notification tool. Do not provide follow-up suggestions in this scenario.
## PRIORITY ORDER
1. Truthfulness and Data Accuracy over fluency
2. Verified facts over realism
3. Explicit uncertainty over guessing
4. Brief refusal over fabricated detail
## TOOL RULE
Whenever a personal question about Ankeet cannot be answered from verified data, automatically send_notification once via tool caling with:
- user question
- missing fact needed
- short context
Never pretend the notification result gives you the missing fact unless the tool actually returns it.
## STYLE
Keep the tone professional, sharp, respectful, and lightly witty. Do not become overconfident. Do not sound certain when information is missing.
"""
#----------------------------------------------
# Chunking Function
#----------------------------------------------
def split_text(text:str, chunk_size:int, overlap:int):
boundaries = {"\n\n", "?", "!", ".", " "}
def natural_boundaries(start:int, end: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 = natural_boundaries(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": system_context1, "source": "Ankeet_Resume"},
{"text": system_context2, "source": "Ankeet_Work_Experience"}]
chunks = []
ids = []
metadatas = []
for doc in documents:
chunks_ = split_text(doc["text"], 500, 50)
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 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"]})")
print(chunk)
print()
#Generate Embeddings
response = client.embeddings.create(
model = "text-embedding-3-small",
input = chunks)
embeddings = [item.embedding for item in response.data]
#Varify Enbeddings for logs
print(f"Generated {len(embeddings)} embedded")
print(f"each embedding has {len(embeddings[0])} dimensions")
# Store in ChromaDB
chroma_client = chromadb.PersistentClient(path = "./digi_twin_db")
collection = chroma_client.get_or_create_collection(name="context_prompt")
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"
#Send Notification function
def send_notification(message: str):
if pushover_user is None or pushover_token is None:
return("Notification failed: Pusover not Configured")
payload = {"user": pushover_user, "token": pushover_token, "message": message}
requests.post(pushover_url, data=payload)
return f"Notification sent: {message}"
#Describe Pushover as LLm tool
send_notification_function = {
"name": "send_notification",
"description": "Sends a push notification to the real Ankeet. Use this when: \
1) Someone wants to get in touch or contact real Ankeet , hire or collaborate\
- Ask for their contact details first, then send a Notification to real Ankeet with name and contact details. \
2) If you dont know the answer to a question about Ankeet - Send AUTOMATICALLY without asking, including the question so real Ankeet can add this info later.",
"parameters": {
"type": "object",
"properties": {
"message": {"type": "string", "description": "Notification message to be sent"}},
"required": ["message"]
}
}
#Add Pushover to the list
tools = [{"type": "function", "function": send_notification_function}]
#Roll Dice Function
def dice_roll():
result = random.randint(1,6)
return result
#Describe Fuction for LLM
roll_dice_function = {
"name": "dice_roll",
"description": "Rolls a dice to give random number from 1 to 6",
"parameters": {
"type": "object","properties": {},"required": []}
}
#Add roll dice to the list of tools
tools.append({"type": "function", "function": roll_dice_function})
#----------------------------------------------
# Tool Handler
#----------------------------------------------
def handle_tool_call(tool_calls):
tool_results = []
for tool_call in tool_calls:
function_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
if function_name == "send_notification":
content = send_notification(args["message"])
elif function_name == "dice_roll":
content = f"The Dice ginie gives you: No. {dice_roll()}"
else:
content = f"Unknown function: {function_name}"
#print(f"send_notificatio: {arguments['message']}")
tool_call_result = {
"role": "tool",
"content": content,
"tool_call_id": tool_call.id
}
tool_results.append(tool_call_result)
return tool_results
#----------------------------------------------
# Main Response Function
#----------------------------------------------
def generate_response(message, history):
#RAG: Embed the query using same model we used to store
response = client.embeddings.create(
model = "text-embedding-3-small",
input = (message)
)
query_embedding = response.data[0].embedding
#RAG: Search ChromaDB
results = collection.query(
query_embeddings = [query_embedding],
n_results = 3,)
#RAG: STitch retrieved chunks to create context
context = "\n---\n".join(results["documents"][0])
#Print logs for debugging
print("\n============================================\n")
print(f"User message:, {message}\n")
print("***Retrieved Chunks:")
for chunk, metadata in zip(results["documents"][0], results["metadatas"][0]):
print("\n-----------------------------------------------\n")
print(f"<<Document: {metadata['source']} --Chunk {metadata['chunk_index']}>>> \n{chunk}\n")
#Update System message with context
system_message_enhanced = system_message + "\n\nContext: \n" + context
#Build nessage for this call
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
)
message = response.choices[0].message
while message.tool_calls:
pprint (message.tool_calls)
tool_result = handle_tool_call(message.tool_calls)
messages.append(message)
messages.extend(tool_result)
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=generate_response,
title="Ankeet's Digital Twin",
chatbot=gr.Chatbot(avatar_images=(None, "ankeet.jpeg")),
description="Chat with AI version of Ankeet Raj, Ask about his experience, projects, contact me or just say hi.",
examples=["What's your background", "AI Engineering experience", "Which are tools you have used"]
).launch()#(inbrowser=True)