Machine Learning Engineer / Data Scientist

Joaquin Ramirez

I've spent three years building GenAI products and predictive models that made it to production: an AI copilot used by 1300+ organizations, fraud detection for a network of 35 banks, forecasting and optimization for exporters and retailers. Now an MSBA candidate at UCLA Anderson.

Los Angeles, CA · Seeking Summer 2027 internships in AI product management and data science

Selected work

AI copilot and agents for HR teams

Crehana (HR-tech SaaS) · Senior Machine Learning Engineer · Feb 2025 – Sep 2026

I led development of Crehana's GenAI copilot and the agentic systems behind it (LangChain, LangGraph), used across Latin America. When our data-extraction agent kept failing in production, I redesigned its routing and added reliability safeguards: failures dropped 25%, and adoption of the whole copilot grew 9x. I also presented tradeoffs to our executive committee and coordinated the work of two other ML engineers.

1300+ organizations 48K+ users agent failures −25% adoption 9x

LangChain · LangGraph · OpenAI · Python · AWS · case study →

The retrieval pipeline behind the copilot

Crehana · Senior Machine Learning Engineer · Feb 2025 – Sep 2026

The copilot answers from each company's own documents, so the retrieval layer has to stay fresh and tenant-aware. I built and ran the ingestion pipeline: 10K+ documents a week, indexed on a schedule into a search corpus of 1.2M+ vectors on Qdrant with OpenAI embeddings.

10K+ docs/week 1.2M+ vectors

RAG · Qdrant · OpenAI embeddings · Python · case study →

Contract allocation for a commodity exporter

Canvia (IT consulting) · Data Scientist · Dec 2023 – Dec 2024

A fishmeal exporter planned its contract allocation by hand, two weeks per cycle. I built the product classification and allocation algorithm that now does it in under 20 minutes, raising estimated gross margin by ~55% and cutting operating costs by ~40%. I presented the results to about 15 client stakeholders, including VPs.

est. gross margin +55% costs −40% 2 weeks → <20 min

Python · scikit-learn · optimization · case study →

Fraud detection across 35 financial institutions

Canvia · Data Scientist · Dec 2023 – Dec 2024

Real-time anomaly detection (Isolation Forest) on transactions moving between 35 of Peru's leading financial institutions. The system automatically flags the highest-risk ~2% for human review instead of asking analysts to watch everything.

35 institutions ~2% flagged, real time

Isolation Forest · anomaly detection · Python · case study →

G.E.N.I.E., my undergraduate thesis

UTEC · 2023

A generative chatbot specialized in our university's regulations, built back when that meant doing everything yourself. We scraped and structured the documents, generated a fine-tuning dataset, and LoRA fine-tuned Falcon-7B through 20 hyperparameter trials, taking evaluation loss down 84% (2.92 to 0.46) and perplexity from 18.5 to 1.6, then validated the answers with user testing.

eval loss −84% perplexity 18.5 → 1.6

Falcon-7B · LoRA · Hugging Face · code and full write-up →

Case studies

The HR copilot and its agents

Crehana · how I think about agents, reliability, and product

Who uses it and for what

HR admins, managers, and employees, each with different jobs to be done. An employee asks what their company's paternity leave policy allows, and the copilot answers from the documents their HR team uploaded. Another asks how they did against their quarterly goals, which triggers a data query and then course recommendations to close the gaps. A team leader asks who on the team is behind on which metrics and how to help them catch up. One interface, very different workflows underneath.

Why agents instead of simpler automation

The use cases that mattered were multi-step and stateful. Onboarding involves a chain of bureaucratic steps over private personal data: cleaning it, validating it, triggering downstream tasks, and, critically, surviving interruption, because managers stop mid-flow and come back later. Complex reporting needs retrieval across different components of the platform's data (we exposed them to the agents through MCP) and a back-confirmation pass before anything reaches the user. A form or a single prompt cannot hold that kind of state or recover from partial failure; an agent can.

Where personal data sat, and where it did not

Personal data reached the models through retrieval, and I did not add model-side redaction. An answer about someone's own onboarding or goals needs the underlying record to be worth reading, so stripping it would have defeated the feature. The control is not redaction, it is authorization: retrieval is filtered by the asking organization and then by what that specific user is entitled to see, so the model is only ever handed records the asker could already open themselves. Upstream, ingestion was owned by data engineering under their security guidelines, and I worked from the curated data they handed over rather than from raw records. The filter has a visible cost worth naming. The copilot regularly answers that there is no data on something when the company holds plenty of it, just not for that user, and the open product question is whether to say that out loud. Telling someone they lack access is clearer than telling them nothing exists, but it also confirms the record exists, which is its own leak.

The reliability work behind the 25% failure reduction

The data-extraction agent failed too often in production: schema-invalid outputs, timeouts, wrong extractions. I attacked it on several fronts: stricter schema enforcement on outputs, redesigned prompts, better validation, a fallback chain so that when a model fails the request retries on a lighter model or a different provider, and a self-critique step where the agent checks that its own answer makes sense before returning it. Failures dropped 25%, and copilot adoption, measured in weekly active prompts, grew 9x.

Extraction request Model call Lighter model, then a different provider Schema enforcement Self critique Returned to the user output clears both call fails retried output rejected, retry
One extraction request. Everything the model produces, first call or fallback, has to clear both gates before anyone sees it: output that does not match the schema, and answers that do not survive the model's own critique, go back for another attempt. Those two gates are what the reliability work added.

Working with the business

I presented tradeoffs to an executive committee of the CEO, CTO, and product lead: where the AI team should go next, which products the company needed, how to weigh bug fixes against new capabilities. Part of that job was advocating for what the engineering roadmap needed, not only what the business asked for.

Back to top ↑

The retrieval pipeline behind the copilot

Crehana · multi-tenancy, messy inputs, and honest evaluation

What actually flows in

It is not a static document pile. Information flowed continuously from the platform's HR modules into the master database as companies edited, uploaded, and generated records, more than 10K documents a week. Every weekend the pipeline reindexed that into a search corpus of 1.2M+ vectors on Qdrant, using OpenAI embeddings over overlapping chunks.

Multi-tenancy: the constraint that shapes everything

1300+ organizations share the platform, and no company may ever see another company's data. Retrieval enforces metadata filtering per organization on the vector side, on top of tenant schemas in the relational database. I also evaluated moving to separate collections per tenant, which buys stronger isolation and much simpler offboarding when a customer leaves, at the cost of operational overhead across that many organizations. Filtered search won for now; I still think the isolation argument gets stronger as the platform grows.

Every weekend HR platform records edited and created continuously Files companies upload docs, slides, sheets, PDFs, audio Preprocessing per format Chunking with overlap, embedding Vector store 1.2M+ vectors, reindexed weekly 10K+ documents a week At question time Question, from one company Retrieval filtered to that company searched Answer grounded in that company's own text
The pipeline, and the line that matters. Retrieval is filtered to the asking organization, so one company's question can only ever be answered from that company's own material. Everything above that gate is shared plumbing; the gate is what makes it safe to share.

The pivot that taught me the most

Companies started uploading every kind of file: Word, PowerPoint, Excel, PDFs, even audio, far beyond the HR documents the system was designed for, and they expected answers. Fair expectation, wrong assumption in our design. We rebuilt preprocessing per format, redesigned chunking and indexing, and replaced single-pass similarity search with a retrieval approach that held up across all those formats. Answer quality improved notably without giving up speed.

How I evaluated it, honestly

We maintained a golden set of 200 questions and scored every change against it on answer accuracy. That is a real but limited signal: a fuller evaluation would add retrieval-level metrics like hit rate and MRR, which is where I would invest next. On infrastructure: Qdrant was chosen before I arrived, and it held up at our scale, so replacing it was never the priority.

Back to top ↑

Contract allocation for a commodity exporter

Canvia · turning a two-week manual process into a 20-minute optimization

The problem, from zero

Fishmeal sells by quality band (super prime, prime, and lower grades), and a pile's band is determined by its measured composition: protein, fat, histamine, and other metrics. The interesting part is that piles can be blended, and blending produces a new pile with a new composition. The goal is not to maximize premium volume; it is to maximize revenue across all contracts. And blending has hard constraints: some piles can be blended up into a higher band, while others can never reach it no matter what you mix them with.

Allocation adds a second layer. Clients contract tonnage per quality band, and partial fulfillment is not free: if a contract takes most of a quality's stock, the leftover tons must still meet that band's composition to be sellable later. Piles come in fractional weights and live in physical bags, and splitting a bag is expensive and slow, so the plan has to hit contract tonnage as closely as possible while splitting as few bags as possible and keeping every composition constraint intact.

What existed before

Around five analysts working across Excel sheets, hand-picking piles by trial and error, hoping to maximize revenue. Two weeks of planning even for small contracts.

What I built

A branch-and-bound search over blend and allocation combinations: I enumerated the combinations as a tree and pruned aggressively, cutting a whole branch as soon as partial results proved it could not contain a better solution. Planning went from two weeks to under 20 minutes. The client asked for delivery through Azure Power Apps, so that is how it was deployed, and I presented results to about 15 client stakeholders, including VPs. Building on their stack instead of the one I would have picked, then standing in their room to defend the numbers, is the forward deployed shape of this work, and it is the part I want more of.

Where the numbers come from

The estimated 55% gross margin improvement and 40% lower operating cost come from a month of testing on the client's real data, comparing the algorithm's plans against the plans their own team produced, with the client providing the feedback and the baseline. That is why I say estimated: it is their measurement of our output against their old process, not a projection I invented.

Back to top ↑

Fraud detection across 35 financial institutions

Canvia · unsupervised learning under real-world constraints

What it watched

Interbank transfers between 35 of Peru's leading financial institutions, in real time. The feature engineering encoded what fraud tends to look like: account age, deviation from a person's normal transfer amounts, transfers between someone's own accounts across different banks, activity at unusual hours, unusual bank-to-bank combinations. The model then decided what was anomalous in that feature space.

Why Isolation Forest

The client could not provide fraud labels, which rules out supervised learning and is exactly the setting unsupervised anomaly detection exists for. I inherited a first MVP that flagged around 9% of transactions, far more than review capacity. I redesigned the features and the model and brought flags in line with the client's ~2% operating threshold. With labels, I would revisit the choice: semi-supervised methods or a supervised model trained on confirmed cases could well beat it.

What real time required

A fast, concurrent API (FastAPI), hosted on-premise with no cloud services allowed, which meant working hand in hand with the infrastructure team on latency and concurrency budgets.

Scope, honestly

The 2% threshold was the client's operating requirement, sized to their review capacity. A deeper analysis of false positives against missed fraud sat outside the engagement's scope: our mandate was the model and the flagging API, and the client consumed the alerts downstream. If I owned the product end to end, that precision-recall analysis is the first thing I would add.

Back to top ↑

Skills

AI & ML
LLMs and GenAI (OpenAI, Claude, Gemini) · agentic systems (LangChain, LangGraph) · RAG · vector databases (Qdrant) · scikit-learn · NLP
Analytics
A/B testing · hypothesis testing · forecasting · anomaly detection · classification
Programming
Python (pandas, NumPy) · SQL · R · C++
Tools & Cloud
AWS · Azure · GCP · Docker · Git · Tableau · Power BI
Languages
Spanish (native) · English (fluent) · German (B2)

Education

UCLA Anderson School of Management

Master of Science in Business Analytics (MSBA), expected December 2027 · Anderson Merit Fellowship

Universidad de Ingeniería y Tecnología (UTEC)

B.S. Computer Science, 2024 · Top 10% of class, Academic Excellence Scholarship · Student Body President (2022) · Exchange year at Hochschule Luzern, Switzerland

About

Joaquin Ramirez

I grew up in Lima, Peru, and moved to Los Angeles in September 2026 for the MSBA at UCLA Anderson. Spanish is my first language, English is my working one, and I still speak the German I picked up during an exchange year in Switzerland.

Away from a keyboard you will find me eating, a lot, with hot sauce on absolutely everything, breakfast included. I cook recipes I watched on TikTok exactly once, play football (the kind you play with your feet) and basketball, and take any excuse to explore somewhere new. I binge entire shows in a weekend and forget the whole plot a few days later, and I will defend Dua Lipa's discography without shame. If any of that sounds like your kind of conversation, my inbox is open.