惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
量子位
D
DataBreaches.Net
博客园 - 司徒正美
J
Java Code Geeks
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
B
Blog
The Cloudflare Blog
D
Docker
I
InfoQ
爱范儿
爱范儿
MongoDB | Blog
MongoDB | Blog
腾讯CDC
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
S
SegmentFault 最新的问题
GbyAI
GbyAI
有赞技术团队
有赞技术团队

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Shipping an LLM-powered "lie detector" in a Flutter datin...
Vlad Vladescu · 2026-06-12 · via DEV Community

Vlad Vladescu

How I added a production AI feature to Naked — a psychology-based dating app — using Flutter, Firebase Cloud Functions, and the Claude API.

The product problem
Naked matches people on psychological compatibility: users complete assessments (attachment style, communication style, Big Five…) and get matched on the results. But self-reported questionnaires have a known weakness — people answer how they want to appear, not how they are. A rule-based scoring engine can compute "your attachment style is anxious"; it cannot notice that question 4 and question 11 contradict each other.

That pattern-level analysis is exactly what LLMs are good at. The feature: after completing any assessment, the user can request an AI Insight that analyzes the raw answer pattern — strengths, growth areas, a dating tip, and a consistency analysis that flags contradictions, fence-sitting (all-neutral answers), and social-desirability bias. Once the user's match completes the same test, the insight upgrades with a couple-dynamics comparison.

Architecture
Flutter app (quiz UI, BLoC + Clean Architecture)
│ httpsCallable — Firebase Auth token attached automatically

Firebase Cloud Function (Node.js, the only holder of the API key)
│ auth gate → payload validation → cache check → Claude call

Claude API (claude-opus-4-8, schema-enforced structured output)


Firestore (insight persisted per user/test + token-usage audit trail)
Five decisions I'd defend in any review

  1. The API key never ships in the binary. Anything inside an APK/IPA can be extracted in minutes. The app only talks to a Firebase callable function that requires an authenticated user; the Anthropic key lives in Firebase Secret Manager and exists only inside the function's runtime.

  2. Structured outputs instead of "please reply in JSON". The Claude call uses a JSON schema the API enforces — including enums for the consistency verdict and confidence. No regex extraction, no retry-on-malformed-JSON, and the Flutter side parses straight into typed entities.

  3. Cost discipline from day one. On a paid path, never trust the client: the function caps answer counts and string lengths so a tampered client can't inflate token spend. Responses are cached in Firestore keyed by a SHA-256 hash of the inputs — an identical request is served free. Every generation stores its token usage, so spend is auditable per user from the console.

  4. Cache invalidation by design, not by flag. The cache hash includes the partner's result. Same answers + no partner and same answers + partner data are different hashes — so when the match completes the test, a refresh regenerates the insight automatically. The hash is the staleness check.

  5. A privacy boundary the model must respect. The consistency analysis is private: Firestore rules make insights readable only by their owner, and the system prompt explicitly forbids leaking candour observations into the shared partner-dynamics text. Only the partner's computed result is ever sent to the model — never their raw answers.

Process
TDD: the BLoC tests were written before the implementation — 8 tests covering success, failure, double-tap guarding, stored-insight loading, and partner-aware refresh, with the repository mocked.
Inputs persisted, not just outputs: every quiz submit snapshots the raw answers, so insights can be regenerated later (e.g. when the partner finishes the test) without retaking the quiz.
Production debugging: the first deploy failed transiently mid-creation, leaving the callable without its public-invoker IAM binding (403 at the HTTP layer before any code runs). Diagnosed with a curl smoke test, fixed with one gcloud IAM command — a reminder that "deployed" isn't "verified".
Stack
Flutter · BLoC + Clean Architecture · Firebase (Auth, Firestore, Cloud Functions, Secret Manager) · Claude API (claude-opus-4-8, structured outputs) · Node.js · mocktail/bloc_test

Vlad Vladescu — Senior Mobile Engineer (Flutter & Android), ex-British Telecom (EE app, 12M+ users). Open to senior Flutter / mobile-AI roles, remote EU. linkedin.com/in/vlad-vladescu-180733121

flutter, #ai, #firebase, #mobile