Work

Internships — what I built and what I learned.

Novarroh TechnologiesJuly 2025 – Sept 2025
AI Engineer Intern · Remote
Google ADKPythonLiteLLMGCP

What I built

The problem: LLM system prompts encode behavioral rules — "never discuss competitors", "always respond formally", "must not reveal pricing". Testing whether an LLM actually follows those rules at inference time is tedious manual work. My job was to automate it.

I built a pipeline that takes a system prompt as input and outputs a complete adversarial test suite — hundreds of prompts designed to break each rule, across every angle of attack.

Pipeline architecture

The pipeline runs in two stages. First, a parser extracts typed behavioral norms from the system prompt — classifying each rule as MUST/SHOULD/MAY with actor, condition, and action fields. A 50-norm system prompt typically yields 40–55 extracted rules after deduplication.

Second, for each norm, a 4-stage SequentialAgent generates adversarial prompts: (1) sieve — confirm the norm is testable, (2) goal cluster — group related norms, (3) coverage plan — decide which adversarial techniques to apply, (4) prompt generation. All 50 dimensions run in parallel — one SequentialAgent per dimension, spawned dynamically at runtime.

Map-Elites for coverage

The naive approach — random sampling across adversarial techniques — clustered around easy cases. You'd get 40 variations of "ignore previous instructions" and zero prompts testing multi-turn persona switching.

I adapted Map-Elites, a quality-diversity algorithm, to maintain a coverage map across 8 adversarial techniques × 50 norm dimensions. The algorithm explicitly rewards filling empty cells, ensuring every (technique, norm) pair gets tested. After 200 iterations on a customer service prompt, Map-Elites covered all 50 dimensions vs 31 for random sampling.

Scale

A single test run against a 50-norm system prompt generates hundreds of LLM calls in parallel. Each generated prompt carries metadata: norm ID, adversarial technique used, evaluation criteria, and violation behavior. This makes the test suite actionable — not just "the LLM failed" but "norm #14 failed under persona injection, expected X, got Y".

Yonata Software Pvt LtdJuly 2024 – Sept 2024
Software Engineer Intern · Remote
PythonWeaviateMistralFastAPINext.js

What I built

A clinical RAG pipeline for a cardiovascular and diabetes pilot. The system matched 800 synthetic patient profiles against 10,000 chunks of clinical guidelines, and surfaced recommendations through a validation platform used by five physicians.

Ingestion pipeline

Clinical guidelines come as PDFs with tables, numbered lists, and embedded figures. I used Mistral to convert PDFs to markdown before chunking — this preserved table structure better than naive text extraction, which matters for dose tables and diagnostic criteria.

Chunks were indexed in Weaviate with a metadata schema separating searchable index from full document storage: guideline name, section, condition, evidence grade. This allowed filtering by condition and evidence grade before vector search, dramatically reducing the candidate set.

The 89% recall problem

Automated eval showed 89% retrieval recall — the relevant chunk appeared in the top-5 results 89% of the time. Felt good. Then the physicians rejected 40% of suggestions.

The gap: automated eval measured topical relevance, physicians measured clinical appropriateness. A patient with Type 2 diabetes and chronic kidney disease has different medication guidelines than one without CKD. Our retrieval found diabetes chunks (high recall) but missed comorbidity-specific sections (low clinical precision).

I added a second retrieval pass for comorbidities: a lightweight classifier extracted comorbidities from the patient profile, then ran a targeted search for sections mentioning those conditions in combination. Physician acceptance went from 60% to 79%.

Validation platform

Built a 5-physician review interface with per-section review, inline editing, and confidence scoring. The initial confidence score was raw cosine similarity — physicians learned to distrust it fast. We replaced it with a calibrated score: similarity × evidence grade weight × comorbidity match score. Still imperfect, but it incorporated clinical structure rather than pure semantic distance.