JPJayraj Patel
← All projects
CASE STUDY · PERSONAL PROJECT · ORACLE APEX

Ask Jayraj: AI Resume Assistant

Ask anything about my experience. Answers come only from my verified profile, retrieved with Oracle AI Vector Search – never guessed.

LiveOracle APEXPL/SQLOracle AI Database 26aiAI Vector SearchRAGGemini APIREST

OVERVIEW

A public AI assistant that answers recruiters' questions about my experience, skills and availability. Built end to end in Oracle APEX and PL/SQL on Oracle AI Database 26ai, using the Gemini API for language and embeddings. Runs at zero cost on apex.oracle.com's free tier.

THE PROBLEM

Recruiters skim a resume in seconds and often have one specific question ("Has he led a team?", "What's his notice period?"). A generic AI chatbot would invent answers; this one must only use verified facts.

HOW IT WORKS

  1. AskThe visitor asks a question in any wording, with typos or in another language.
  2. RewriteGemini cleans the question (fixes spelling, expands abbreviations, translates); meaningless input is detected and the visitor is asked to rephrase.
  3. EmbedThe question becomes a 768-dimension vector (Gemini embedding model).
  4. Vector searchOracle AI Database 26ai finds the closest profile chunks by cosine distance (top 8, with a relevance cut-off) in a native VECTOR column.
  5. Grounded answerGemini writes the reply using only those chunks; if they don't contain the answer, the assistant says it doesn't know and points to my email.
  6. LoggingEvery question, rewritten query, chunks used, response time and feedback is stored.

Questions about availability, notice period or salary are detected after the rewrite step and answered with a fixed redirect to email/LinkedIn, so no search or AI call is made.

Ask Jayraj architectureArchitecture: the visitor's browser calls two APEX Ajax callbacks, ASK_AI and FEEDBACK. ASK_AI runs ASSISTANT_PKG.ask inside Oracle AI Database 26ai on apex.oracle.com: rate limits, rewrite, embed, vector search, answer, sources and logging, using the KB_CHUNKS, KB_DOCS and AI_CHAT_LOG tables. AI_PKG is the only part that calls the external Gemini API, using an encrypted APEX Web Credential. A daily DBMS_SCHEDULER job fetches my CV as one-fact lines from the key-protected jayrajpatel.com/api/profile, compares its SHA-256 fingerprint, and only when it changed rebuilds the knowledge base, turning KB_DOCS into embedded KB_CHUNKS. Visitor's browser · APEX pagequestion box, example chips, answer with sources, thumbs up/down, live stats ASK_AI Ajax callbackassistant_pkg.ask(question, session) FEEDBACK Ajax callbacksaves thumbs up/down in AI_CHAT_LOG ORACLE AI DATABASE 26AI · APEX.ORACLE.COM ASSISTANT_PKG.askrate limits → rewrite → embed → vector search → answer → sources → log TablesKB_CHUNKS with VECTOR(768)KB_DOCS · AI_CHAT_LOG AI_PKGcall_gemini: retry with backoffembed · generate · fallback model Knowledge base buildKB_DOCS → KB_BUILD_CHUNKS → KB_CHUNKS Daily sync jobDBMS_SCHEDULER · SHA-256 check · rebuild on change Gemini APIchat + embeddingmodels Web CredentialsGemini key · profile key jayrajpatel.com/api/profilemy CV as one-fact lines · key-protected Ask Jayraj architectureArchitecture: the visitor's browser calls two APEX Ajax callbacks, ASK_AI and FEEDBACK. ASK_AI runs ASSISTANT_PKG.ask inside Oracle AI Database 26ai on apex.oracle.com: rate limits, rewrite, embed, vector search, answer, sources and logging, using the KB_CHUNKS, KB_DOCS and AI_CHAT_LOG tables. AI_PKG is the only part that calls the external Gemini API, using an encrypted APEX Web Credential. A daily DBMS_SCHEDULER job fetches my CV as one-fact lines from the key-protected jayrajpatel.com/api/profile, compares its SHA-256 fingerprint, and only when it changed rebuilds the knowledge base, turning KB_DOCS into embedded KB_CHUNKS. Visitor's browserAPEX page: question, chips,answer with sources, stats ASK_AIAjax callback FEEDBACKAjax callback · log ORACLE AI DATABASE 26AI ASSISTANT_PKG.askrate limits → rewrite → embed→ vector search → answer→ sources → log TablesKB_CHUNKSVECTOR(768)KB_DOCS · LOG AI_PKGcall_geminiretry · fallback KB buildKB_DOCS →KB_BUILD_CHUNKS→ KB_CHUNKS Daily syncDBMS_SCHEDULERSHA-256 checkrebuild on change jayrajpatel.com/api/profilekey-protected CV Gemini APIchat + embeddings Web CredentialsGemini · profile key
Architecture – everything except the language model and my CV feed runs inside Oracle

KNOWLEDGE BASE · SYNCED AUTOMATICALLY FROM THIS WEBSITE

My website is the single source of truth. It exposes my CV at a private endpoint (/api/profile, protected by an API key) as one self-contained fact per line, plus a SHA-256 fingerprint header. In Oracle, a scheduled PL/SQL job runs daily:

  1. Fetches the profile using an APEX Web Credential (the key is never in code)
  2. Validates it: HTTP 200, plain-text content, valid fingerprint, minimum line count, and content rules (no phone numbers, no restricted topics); a bad fetch never touches the knowledge base
  3. Compares the fingerprint with the last sync; if unchanged, it stops with no AI calls (about 0.2 seconds)
  4. If changed, it replaces the CV document and re-embeds it (34 facts in about 25 seconds) in a single transaction, so visitors never see a half-built knowledge base and a failure rolls back automatically
  5. Logs every run as UNCHANGED, UPDATED or FAILED with the reason

When I update this website, the assistant updates itself, with no manual data entry. A small manual FAQ holds only redirects (availability, notice period and salary go to email/LinkedIn).

GUARDRAILS AND ENGINEERING

INTERESTING PROBLEMS I SOLVED

“Messy questions missed the right facts”

→ Added a query-rewrite step before the vector search.

“Log rows looked missing”

→ On Oracle RAC, identity values are not in time order; sorted by timestamp instead.

“In-database embedding model not allowed on the free tier”

→ Generated embeddings via Gemini, kept storage and similarity search inside Oracle.

“Keeping the assistant in sync with my CV”

→ Replaced hand-maintained knowledge-base tables with a daily job that pulls from my website, detects changes by fingerprint and only re-embeds when something changed.

“Background job couldn't read Web Credentials”

→ A scheduler job runs outside APEX, so it creates an APEX session for the app before syncing and removes it afterwards.

“Free-tier model overloads”

→ Retry with backoff, then a lighter primary model and a fallback; response time dropped from about 20 seconds to a few seconds.

TRY IT

Loads the assistant from Oracle APEX, right here on the page.

Not loading? Open the assistant in a new tab

TECH STACK

Oracle APEX 26.1PL/SQLOracle AI Database 26ai (AI Vector Search)Gemini API (generation + embeddings)APEX_WEB_SERVICEDBMS_SCHEDULERAPEX_SESSIONSHA-256 change detectionJSON_OBJECT_TJavaScript (apex.server.process)Cloudflare Pages Functions
← Back to all projects
CONTACT

Let's talk.

Work, photography collaborations, or just hello.

LinkedIn Instagram

Prefer email? jayraj.patel1407 [at] gmail.com