← Portfolio
Personal Project · 2026 · Full-Stack · Next.js 14 + FastAPI + LangChain RAG

Gnosis AI —
Conversational Analytics

Upload a CSV. Ask anything. Get an answer in seconds — no code, no account, no setup.

Next.js 14 + TypeScript FastAPI + LangChain RAG 5 LLM Providers 13 ML Tools 150 Tests · 80% Coverage SSE Streaming

Το AI ψάχνει στα δικά σου δεδομένα πριν απαντήσει (RAG), αντί να μαντεύει.

~11K
Lines of Code
5
LLM Providers
13
ML Tools
150
Tests · 80% Cov.
Summary
Solo Full-Stack Build · Product + Engineering · 2026

Full-stack conversational analytics platform: upload a CSV, ask in natural language, a RAG layer picks the right Python tool and streams the answer — no code, no account.

LLM = Large Language Model (π.χ. GPT, Llama) — μεγάλο μοντέλο τεχνητής νοημοσύνης εκπαιδευμένο να καταλαβαίνει και να απαντά σε φυσική γλώσσα.
~11,200 γραμμές κώδικα · 24 frontend files · 5 LLM providers με runtime switching · 13 ML tools
150 tests · 80% coverage gate · CI on every push · Docker multi-stage build · Vercel + HuggingFace Spaces
Next.js 14 · React 18 · TypeScript FastAPI · Python 3.11 LangChain RAG · Chroma Groq · OpenAI · Gemini · Ollama scikit-learn · pandas · reportlab pytest · GitHub Actions · Docker
Next.js 14 App Router FastAPI + LangChain Chroma Vector Store SSE Streaming 13 ML Tools BYOK · Local Execution
9
Test Modules
<1s
First Token P90
3
Entry Points
2h
Session TTL
0
Required Signups
The Problem
Why this product exists

Exploratory tasks — έλεγχος ποιότητας, correlations, quick regressions — είναι μηχανικά, όχι expert judgment. Οι λύσεις όμως αναγκάζουν επιλογή: Jupyter (Python fluency) ή ακριβό BI tool (Tableau, Power BI). Καμία βελτιστοποιημένη για την πρώτη επαφή με ένα dataset.

Product thesis: Η διεπαφή είναι chat window, όχι φόρμα. Natural language αφαιρεί το overhead του να μαθαίνεις ένα UI — το dataset γίνεται το primary object of attention.
User Research
7 informal discovery conversations · 4 in-person · 3 remote · 0 screeners · 0 incentives

7 informal συζητήσεις με non-data-scientists, πριν γραφτεί κώδικας — τους ζήτησα να περιγράψουν την τελευταία φορά που χρειάστηκε να καταλάβουν γρήγορα ένα CSV.

«Ξέρω τι θέλω να μάθω. Απλώς δεν ξέρω πώς να το ζητήσω από το Excel. Ο pivot table μου πήρε 20 λεπτά και δεν είμαι σίγουρος αν τα νούμερα είναι σωστά.»

P1 — Marketing Manager → Το intent είναι ξεκάθαρο· το tool interface είναι το bottleneck. Το natural language αφαιρεί το translation layer.

«Το ChatGPT μου έδωσε ένα wall of text. Απλώς ήθελα έναν αριθμό και ένα chart. Κατέληξα να το κάνω στο Excel ούτως ή άλλως.»

P2 — Business Analyst → General-purpose LLMs παράγουν κείμενο, όχι analysis. Ένα tool-routing layer που εκτελεί πραγματικούς υπολογισμούς είναι fundamentally different product.

«Χρειάζομαι απάντηση τώρα, όχι ένα dashboard την επόμενη εβδομάδα.»

P6 — Product Manager → Latency είναι το primary pain, όχι η ποιότητα. Τα SSE tokens ξεκινούν να εμφανίζονται σε κάτω από 1 δευτερόλεπτο.
3 User Archetypes
Behavioural patterns από 7 interviews — όχι demographics
The Question Owner
P1, P5, P6 · Marketing / Ops / PM
Ξέρει ακριβώς τι θέλει να μάθει· μηδέν ενδιαφέρον για tools ή κώδικα. Λύνει με delegation ή pivot-table workarounds. BLOCKER → Tool interface overhead. Ξέρει τι να ρωτήσει, όχι ποια Excel formula το εξάγει. ACTIVATION → Fast answer + chart σε <60 sec. High LTV — επιστρέφει με κάθε νέο dataset.
The Stranded Analyst
P2, P3, P4 · BA / PhD / Founder
Κάποιο technical exposure — notebook, ChatGPT — αλλά χτυπά τοίχο στο execution. Ξέρει «χρειάζομαι Random Forest», δεν μπορεί να το γράψει. BLOCKER → Execution gap. Ξέρει τον σωστό analysis type· δεν μπορεί να τον εκτελέσει. ACTIVATION → First ML tool run. Context-aware chips με ονόματα analyses που ήδη γνωρίζει.
The Confidence Seeker
P7, P3 · Journalist / Researcher
Μπορεί να παράγει chart, αλλά δεν εμπιστεύεται την απάντηση — δουλεύει δημόσια όπου ένα λάθος νούμερο έχει συνέπειες. BLOCKER → Confidence gap. Παίρνει απάντηση· δεν μπορεί να την επαληθεύσει. ACTIVATION → PDF report με N, confidence intervals, feature importance. Το πιο δύσκολο archetype.
The Analytical Loop
Upload → Ask → Route → Execute → Stream → Ask again
1
Upload
CSV / Excel / JSON
2
Ask
Natural language
3
Route
LLM selects tool
4
Execute
Python runs analysis
5
Stream
SSE tokens + chart
⟳ Multi-turn: chat history στέλνεται με κάθε request · κάθε απάντηση προτείνει την επόμενη ερώτηση
RAG ως Semantic Router, όχι Chatbot: Εδώ το RAG κάνει ένα job: semantic tool selection. Οι περιγραφές των 13 tools — όχι τα user documents — γίνονται embedded με sentence-transformers/all-MiniLM-L6-v2 και αποθηκεύονται στο Chroma. Το LLM δεν βλέπει raw data ούτε γράφει code — μόνο επιλέγει ποια pre-tested function να καλέσει.
13 Analytical Tools
Tool catalogue · registry-driven · zero boilerplate να προσθέσεις νέο
Tool Category What it does
run_statistical_analysisstatsDescriptive stats, distribution summary, outlier flags
run_random_forestclassificationClassification / regression με feature importance chart
run_machine_learningauto-mlGeneral ML runner — auto-selects best algorithm
run_correlation_analysisanalysisPearson matrix, top correlated pairs
run_regressionregressionLinear / logistic regression με coefficients
run_clusteringunsupervisedK-means / DBSCAN με cluster assignment
run_time_seriestemporalDecomposition, trend, seasonality
run_forecasttemporalForward projection από time column
run_data_quality_checkutilityMissing values, duplicates, type mismatches
plot_chartvizCustom chart από natural language description
clean_datautilityImputation, deduplication, type coercion
generate_pdf_reportexportFull analysis report downloaded as PDF (reportlab)
5 LLM Providers · Runtime Switching
Runtime switching χωρίς page reload · BYOK (key stays in-memory only) · Fully local με Ollama
Groq
Default · fast · free. LLaMA 3, sub-second P90, μόνο API key στο .env.
OpenAI
GPT-4o, υψηλότερο ceiling. Server key ή BYOK — paste in-memory only, σβήνει με το session TTL (2h).
Gemini
Gemini 2.5 Flash, long context. Server key ή BYOK, runtime switchable.
Ollama
Local execution. Όλο το pipeline on-device — zero data egress, μηδέν API key, μηδέν GDPR friction.
Mock
Deterministic stubs για demos/dev — μηδέν key, δουλεύεις αμέσως.
Bring Your Own Key (BYOK): Ένα public, account-free deployment προσφέρει GPT-4o quality χωρίς ο operator να πληρώνει ανά visitor. Το key ζει μόνο in-memory — ποτέ logged.
3 Deliberate Constraints
Architecture decisions που αποκλείουν functionality επίτηδες — και γιατί
Constraint 1 No Email. No Sign-up. No Account.
Every competitor — Julius AI, ChatGPT ADA, Hex, Observable — requires an account before delivering value. Gnosis: open the browser, drop a file, ask. The session UUID in localStorage is the only identity the product needs.

Why: first contact is won or lost in 30 seconds. Trade-off: no persistent identity → no named workspaces or billing tier. Right call for v1.
Constraint 2 Local Tool. Your Data Never Has to Leave.
Every cloud competitor sends user data to an external API. Gnosis supports Ollama as a first-class provider — the entire pipeline runs on-device, zero data egress.

This unlocks governance-constrained users — HR, Finance, Healthcare, Legal — who today either skip AI analytics or violate policy without knowing it. Trade-off: needs capable hardware + a running Ollama instance — one-time setup, not per-user friction.
Constraint 3 Zero Technical Surface. No Code, No Config, No Syntax.
Gnosis never shows code, Python, or SQL — the tool badge (run_random_forest) says what ran, not how.

ChatGPT ADA, Hex, Observable, even Julius AI all surface code. The moment code appears, a meaningful share of target users closes the tab. Trade-off: power users who want to inspect or modify the analysis need Hex or a notebook instead.
Competitive Landscape
Honest positioning — Gnosis κερδίζει σε συγκεκριμένο context, χάνει σε άλλους
Honest positioning: Gnosis κερδίζει όταν ο χρήστης έχει ένα CSV, μηδέν account, μηδέν επιθυμία να δει κώδικα, και χρειάζεται απάντηση σε 10 λεπτά. Χάνει σε live DB connections, team collaboration ή enterprise governance — intentional v1 scope.
Feature Gnosis AI ChatGPT ADA Julius AI Hex
No account required
Free, no message limit$20/mo$35/mo$36/editor
Local / offline execution✓ Ollama
Zero code in outputpartial
Non-technical user readypartialpartial
SSE streaming response
Runtime LLM switching
ML explanations (SHAP)partialpartial
Arbitrary code execution
Team collaborationpaid
Technical Architecture
Next.js 14 Frontend · FastAPI Backend · LangChain RAG · Docker · CI/CD
Frontend
Next.js 14 (App Router), React 18, TypeScript · 24 source files / ~6,885 lines
Streaming
Server-Sent Events (SSE) via useStream hook with cancel support · tokens start in <1s
Backend
FastAPI (Python 3.11) · per-session dataframe store · pydantic-settings config
RAG / Routing
LangChain ConversationalRetrievalChain + Chroma vector store + sentence-transformers embeddings
ML Layer
scikit-learn / pandas · 13-algorithm registry · SHAP-style explanations post-run
Middleware
Sliding-window rate limiter (per session) + request-ID tracing (X-Request-ID)
Deployment
Vercel (Next.js) + HuggingFace Spaces Docker (16GB) · multi-stage build · non-root user · HEALTHCHECK
Export
PDF generation (reportlab) · Markdown export (client-side Blob download) · shareable embed links
Τεχνολογίες σε απλά λόγια:
Embeddings = μετατροπή κειμένου σε αριθμούς, ώστε ο υπολογιστής να συγκρίνει το νόημα δύο προτάσεων.
SHAP = τεχνική που εξηγεί ΓΙΑΤΙ ένα μοντέλο machine learning πήρε μια απόφαση.
DBSCAN = αλγόριθμος που ομαδοποιεί δεδομένα αυτόματα με βάση την πυκνότητά τους.
Docker = πακετάρει την εφαρμογή ώστε να τρέχει ίδια παντού.
CI/CD = αυτόματος έλεγχος & ανέβασμα του κώδικα σε κάθε αλλαγή.
JSON = απλή μορφή κειμένου για ανταλλαγή δεδομένων μεταξύ συστημάτων.
CRUD = οι 4 βασικές λειτουργίες μιας εφαρμογής: δημιουργία, ανάγνωση, ενημέρωση, διαγραφή δεδομένων.
Package isolation, όχι monolith: Το src/gnosis_analytics εγκαθίσταται ως ανεξάρτητο pip package — tests τρέχουν χωρίς running server, CLI δουλεύει χωρίς running Next.js app.
Frontend Architecture · 6 Key Modules
24 source files · TypeScript throughout · state lifted to root — no Redux, no Zustand
Sidebar.tsx
1,021 lines · Dataset upload + LLM switcher
Dataset upload, column inspector, LLM/BYOK switcher, A/B compare trigger, session analytics, PDF export — το πιο πλούσιο component.
UploadLLM SwitchBYOKA/B Compare
MessageBubble.tsx
744 lines · Markdown · Tool badge · ML explanations
Markdown renderer, tool badge, chart card, ML explanation panel («Why did the model choose this?»), retry on error.
MarkdownChartsSHAPRetry
lib/useStream.ts
231 lines · SSE hook με cancel + sentinel detection
SSE hook: connect, append tokens, detect tool sentinels (__tool:X__), cancel, retry-on-silence. Wraps EventSource σε <60 clean lines.
SSEEventSourceCancelSentinel
lib/api.ts
386 lines · Typed API client
Typed API client — upload, chat/stream, async analysis polling, compare, model switch, BYOK key submission. Centralized, no scattered fetch() calls.
TypeScriptTypedPolling
SmartSuggestions
Context-aware chips · zero backend call
4 prompt chips tuned στο loaded dataset. Column-name regex heuristics (/surviv|churn|target|label/) σε binary target detection. Generated synchronously — μηδέν network requests.
Zero API callsHeuristicsChips
ShareModal + OnboardingTour
361 + 395 lines · Share links · First-run tour
ShareModal: copy link / embed <iframe> snippet. Shareable session read-only by ID. OnboardingTour: first-run guided tour anchored to id attributes, gated by localStorage flag.
EmbedsShareOnboarding
Test Suite · 150 Tests
9 test modules · 150 tests · 80% coverage gate · GitHub Actions CI on every push
FileTestsCovers
test_pipeline.py32DataCleaner, DataLoader/Categorizer, StatisticsAnalysis, MachineLearningAnalysis, LLM factory, FastAPI routes, vector store
test_integration.py25End-to-end: health, upload (CSV/Excel/JSON), chat (single & multi-turn), PDF download, session delete
test_tools.py21Thread-local request context, per-tool wrappers, thread isolation under concurrency
test_config.py19pydantic-settings defaults, validation, credential checks
test_run_pipeline.py16CLI/engine entry point (run_pipeline())
test_session.py13SessionStore CRUD, TTL expiry, MAX_SESSIONS cap, LRU eviction
test_async_analysis.py12/analyze/async job lifecycle, status polling, webhook dispatch
test_middleware.py9Rate-limit thresholds, per-session counters, request-ID propagation
test_compare.py3/compare endpoint: row counts, common/disjoint columns
Honest engineering note: Το test_tools.py υπάρχει λόγω πραγματικού regression — thread-local context "έβγαζε" ML results μεταξύ concurrent sessions. Παραμένει στο suite, με το όνομα του bug που έπιασε.
Challenges & Solutions
Real engineering problems που λύθηκαν — όχι smooth sailing
Challenge ML results bleeding μεταξύ concurrent sessions under load — session B έβλεπε briefly τα ML results του session A.
Solution Το thread-local storage δεν γινόταν reset μεταξύ requests στο ίδιο worker thread. Fix: explicit reset στην αρχή κάθε request + regression test που spawns real threads και ελέγχει isolation.
Challenge Streaming tokens με tool-start signals μεμειγμένα στο ίδιο SSE channel — πώς ξέρει το frontend πότε ξεκινά ένα tool;
Solution Sentinel protocol: το backend στέλνει __tool:X__ ως special token πριν την readable response. Το frontend strips το sentinel πριν το rendering, το χρησιμοποιεί μόνο για το toolRunning badge — μηδέν separate control channel.
Challenge Context-aware chips χωρίς backend call σε κάθε dataset load — πώς ξέρεις ποιες suggestions να δείξεις;
Solution Client-side regex heuristics στα column names/dtypes (ήδη επιστρέφουν από το upload endpoint) εντοπίζουν likely targets. 4 chips generated synchronously — μηδέν network requests.
Challenge Mobile keyboard displacing το InputBar off-screen σε iOS/Android.
Solution Resize listener στο window.visualViewport — όταν το viewport shrinks (keyboard open), scrollIntoView κρατά το textarea visible πάνω από το keyboard.
Product Decisions & Trade-offs
Τι επιλέχθηκε, τι απορρίφθηκε, και γιατί — με explicit trade-off log
D1 Chat Interface, not Form/Dashboard
Rejected: Form-based query builder with dropdowns for operation, columns, parameters.
Why chat wins: A form's categories are finite — natural language lets the user ask what the designer didn't anticipate. Cost: ambiguous questions may route to the wrong tool. Mitigated by the tool badge + retry.
D2 Tool Router, not Code Generation
Rejected: LLM generates Python/pandas code on the fly and executes it in a sandbox (à la ChatGPT ADA).
Why routing wins: Generated code fails unpredictably — hallucinated columns, import errors. A pre-tested tool either runs correctly or returns a known error. Cost: unusual analysis outside the catalogue → the user exports to a notebook. Acceptable for v1.
D3 SSE Streaming, not WebSocket
Rejected: WebSocket for bidirectional real-time communication.
Why SSE wins: The pattern is strictly one-directional — client sends, server streams response. SSE runs over plain HTTP/2, auto-reconnects via EventSource, no upgrade handshake. Cost: the server can't initiate messages without a client request — not a constraint here.
Standalone CLI
Ίδιο analytics engine · 3 front doors: Web App / Async Jobs / Terminal
bash — gnosis CLI
# Install engine as pip package
pip install -e ./src

# Run full ML analysis from terminal
gnosis analyze \
  --file data.csv \
  --mode ml \
  --target Survived \
  --algorithms 3,5,12 \
  --output report.pdf

# Modes: stats | ml | all
# Algorithm IDs match the same registry used by the API
Γιατί έχει σημασία: Ο ίδιος tested κώδικας τρέχει και στα τρία contexts — δεν υπάρχει "CLI version" vs "API version". Ένα fix στο engine διορθώνεται παντού.
What's Next
v1 shipped · 3 items in progress · v2 foundation ήδη στο codebase
Shipped (v1)
Async analysis με webhook notification
Server-side A/B comparison με per-column statistical diffing
Standalone CLI wrapper
CI pipeline με Codecov coverage reporting
Multi-stage Docker build + HuggingFace Spaces
In Progress
Phase 2 Panel — clustering, dimensionality reduction
Expanded LLM coverage — Claude API, HuggingFace Inference
Python 3.9–3.11 CI matrix — backwards compatibility pass
v2 Signals
Authenticated sharing → named sessions, persistent workspaces
Plugin tool catalogue — new tools need one registry entry
Database connectors (Postgres, Snowflake)
Team access controls

Έχτισα το Gnosis AI για να απαντήσω σε ένα ερώτημα που συναντούσα συνέχεια: γιατί η exploratory data analysis απαιτεί ακόμα Python fluency ή BI subscription, όταν η ερώτηση είναι συχνά απλή;

Το tool routing δεν ήταν η πρώτη ιδέα — προέκυψε μετά τα 7 interviews, έναν πρώτο prototype που έδειχνε Python code και έχανε τον χρήστη, και έναν thread-local bug που αποκάλυψε πού ήταν το πραγματικό complexity.

Κάθε feature υπάρχει γιατί αφαιρεί friction από συγκεκριμένο user moment — όχι γιατί ήταν technically interesting να χτιστεί.

Spilios Dimakopoulos · Next.js 14 · FastAPI · LangChain RAG · Vercel · 2026
✓ COPIED