DEV Community

Michael Odhiambo
Michael Odhiambo

Posted on

Mikesplore: A Grounded AI Portfolio Assistant

Inspiration

A traditional portfolio usually answers only the questions its creator anticipated when designing the website. If someone wants to know something more specific, they have to search through projects, skills, certificates, or a CV themselves.

I wanted to build a portfolio that could do two things better:

  1. Keep its content easy to update without rebuilding the website.
  2. Allow visitors to ask questions about my experience conversationally.

The result is Mikesplore, a database-backed personal portfolio with a grounded Telegram AI assistant that answers questions using verified portfolio data.

The AI is not the source of truth. The portfolio backend is.


Homepage of mikesplore.me, establishes what the "normal" portfolio looks like before you introduce the bot

What it does

Mikesplore combines a web portfolio, backend API, cloud storage, and Telegram assistant into one system.

Visitors can browse my portfolio normally through the website or interact with the Telegram assistant and ask questions such as:

  • What projects has Mike built?
  • What technologies does he use?
  • Has he worked with fintech?
  • What is his experience with Python?
  • Can I see his CV?


Telegram chat showing 2-3 of the above questions and real answers.

The assistant retrieves information from the portfolio backend before answering. It is designed to avoid inventing information about employers, roles, dates, qualifications, metrics, or experience.

The portfolio administrator can also manage content directly through Telegram, including:

  • Profile information
  • Projects
  • Skills
  • Education
  • Certificates
  • Events and hackathons
  • Links
  • Uploaded media and documents

Potentially destructive or modifying actions require an explicit confirmation step before changes are written to the database.

How it works

The system is built around a simple principle:

Application data should remain the source of truth, while the LLM acts as an interface for retrieving and interacting with that data.

The architecture consists of three main layers.

Frontend

The portfolio website is built with React and Vite and hosted on Vercel.

Instead of bundling portfolio content directly into the frontend, the application loads content from the backend at runtime through REST APIs.

This means I can update portfolio information without rebuilding or redeploying the frontend.

Backend

The backend is built with FastAPI, SQLAlchemy, PostgreSQL, and Alembic.

It provides:

  • Public read endpoints for visible portfolio content.
  • Protected mutation endpoints for administrative operations.
  • Visibility and ordering controls.
  • Portfolio data for projects, skills, education, certificates, events, hackathons, and other sections.
  • Cloudflare R2 file upload handling.
  • CV upload and PDF text extraction.
  • Search over extracted CV content.
  • Database schema migrations using Alembic.

The backend acts as the central source of truth for both the website and the AI assistant.

Telegram AI assistant

The Telegram bot is built with aiogram and uses Groq for LLM inference.

The LLM does not access PostgreSQL directly.

Instead, it uses controlled tools that retrieve information through the backend's APIs. This keeps database access centralized and prevents the bot from becoming an independent source of portfolio information.

The assistant can:

  • Search portfolio entries.
  • Retrieve profile information.
  • Search extracted CV text.
  • List skills and certificates.
  • Send the CV directly to users.
  • Answer questions using retrieved portfolio data.
  • Refuse questions outside the portfolio's intended scope.

This creates the following flow:

User → Telegram → LLM → Controlled tools → FastAPI API → PostgreSQL / R2

The model interprets the user's question, but the portfolio system provides the factual information used to answer it.

Admin management through Telegram

Telegram is not only used as a public interface.

I can also manage portfolio content through the same bot.

Administrative access is protected using two separate controls:

  1. Telegram user ID authorization.
  2. A backend service API key.

The bot can prepare administrative actions, but modifying operations require explicit confirmation before being executed.

This reduces the risk of accidental changes caused by incorrect LLM interpretation or unintended commands.

Security and reliability

Because the assistant represents a real person, reducing unsupported or hallucinated claims was an important design goal.

The system includes:

  • Tool-based data retrieval.
  • Backend-controlled access to portfolio information.
  • No direct database access from the LLM.
  • Instructions against inventing employers, roles, dates, metrics, or qualifications.
  • Refusal of unrelated questions.
  • Telegram webhook secret validation.
  • Administrator Telegram ID whitelisting.
  • Protected backend mutation endpoints.
  • Separate service API key authentication.
  • Explicit confirmation before modifying or destructive operations.
  • CORS restrictions.
  • Upload size limits.
  • PDF validation.
  • Restricted access to sensitive application settings.

The goal is not to treat the LLM as a database, but to treat it as a conversational layer on top of verified application data.

Challenges

Moving from static content to runtime data

One of the biggest challenges was migrating an existing portfolio from build-time content to runtime database-backed content without changing its visual design.

The frontend had to be adapted to load portfolio information dynamically while maintaining the existing user experience.

Controlling LLM behavior

A general-purpose LLM can produce answers that sound confident even when they are not supported by the application's data.

For a personal portfolio, that creates an obvious problem: the assistant could potentially misrepresent the person it is supposed to describe.

I addressed this by limiting the assistant's access to controlled retrieval tools and instructing it to base portfolio answers on retrieved application data rather than general knowledge.

Balancing architecture and hosting cost

The frontend is hosted on Vercel, while the backend is deployed on Render.

Initially, running the Telegram bot as a separate service would have increased the recurring hosting cost. To reduce infrastructure expenses, I mounted the Telegram webhook handling into the FastAPI backend so both components could share a single paid instance.

This reduced cost while keeping the public API and bot functionality available through the same backend deployment.

What I learned

Building Mikesplore reinforced several engineering lessons:

  • An LLM should not be treated as the source of truth for personal or application data.
  • Tool calling can provide a controlled interface between an LLM and verified backend data.
  • Administrative actions generated through natural language should require confirmation before execution.
  • Database-backed content makes a portfolio easier to update and maintain.
  • File uploads require validation, size limits, and clear error handling.
  • Deployment architecture should consider operational cost as well as code organization.
  • A conversational assistant needs clear boundaries in addition to helpful responses.

Future improvements

Planned improvements include:

  • OCR support for scanned CVs.
  • Richer semantic search over CV and portfolio content.
  • Audit logging for administrative changes.
  • Automated tests for protected routes.
  • Background processing for large document uploads.
  • Analytics for commonly asked portfolio questions.
  • Support for additional document types.
  • A small web-based administrative dashboard.

Built with

React, Vite, FastAPI, PostgreSQL, SQLAlchemy, Alembic, aiogram, Groq, Cloudflare R2, Vercel, and Render.

Project links

Live portfolio: https://www.mikesplore.me

Telegram assistant: https://t.me/mikesplorebot

Source code: https://github.com/mikesplore/mikesplore

Top comments (0)