I learned that it's surprisingly straightforward on a Drupal site to set up an AI chatbot that knows your own site content and can talk specifically about it, so I decided to experiment around with one on my own blog.
Right around the time I started on this project, Rod Martin of DrupalHelps created an excellent series of videos on Drupal AI, including a pair on Search Chatbot Part 1 and Part 2, which can walk you through doing this on your own site if you happen to be running Drupal.
Retrieval-Augmented Generation
Retrieval-Augmented Generation, or "RAG", basically means that when you ask the chatbot a question, it first does a search of your site for relevant content and passes it to the AI as context essentially saying "respond using only this information". The AI then generates it's intelligent reply based on your own site content.
Based on my experience so far, it seems accurate and surprisingly resistant to hallucination, since it draws its responses from the context provided to it from the search results.
Frankly, it's main weakness actually seems to be synthesizing a response from multiple source pages. Most of its responses seem to focus on context from one or two pages, at most, even when the question would have benefited from a broader context pulling from many pages. But that's a limitation of how much contextual information is being passed to the AI, which can be tweaked.
Honestly, even with that limitation, I find it quite impressive.
The main magic behind making it work involves processing your site content to generate what's called vector embeddings to be stored in a vector DB. When searching your content for relevant info to pass as context to the chatbot, standard keyword searches are terrible for this.
If a user asks about "infrastructure automation" and my post only uses the word "Terraform", a keyword search gets zero results. Vector embeddings basically turn meaning into math, saving chunks of content (like a paragraph) into hundreds or even thousands of numbers. Those numbers allow it to recognize concepts that are related, like "automated infrastructure" and "Terraform", even when worded completely differently, simply because they're mathematically "close" to each other in the vector db. (Though I confess how those vectors are generated and compared is beyond my current understanding.)
The Drupal Components
For my setup, I used the pgvectors extension to allow me to use my existing PostgreSQL server as the vector DB server. I'm also using several AI-related modules that are already baked into the drupal/cms project: ai, ai_search, search_api, search_api_db, ai_agents, ai_assistant_api, ai_chatbot and ai_provider_openai. I additionally installed and enabled drupal/gemini_provider and drupal/ai_vdb_provider_postgres.
The Lifecycle of a Query
- Input: User inputs a query like "What is Tom's experience with DevOps?" The AI Chatbot block sends the question to the backend
- Vectorization: Drupal sends the question to the embeddings provider ("Gemini | Embedding 001", in my case) to be vectorized, it returns a specific vector.
- Search: Drupal sends that vector to Postgres asking for the closest matches
- Retrieval: Postgres finds (the vectors for) my blog post about "GitOps and CI/CD", because those concepts are mathematically very close to the vectors for "DevOps", and returns the text of those posts.
- Generation: Drupal takes that text, wraps it in a system prompt (something like "You are a helpful assistant. Answer the user using ONLY this context...", only with much more explicit instructions), and sends it to the LLM (I ended up using
GPT-4o-mini). - Answer: The AI reads the context I provided and writes a factual answer citing my specific site content with links.
The end result is a chatbot that "understands" my specific content without the need to train a custom model (a much more significant undertaking).
The Broken Part
The only major problem I've run into (which, as I write this, I've still yet to fix) was a theming issue where, in my version of Drupal, the chatbot window expands to the width of the parent window and grows vertically until the chatbot title bar is off screen, so you can no longer even close the chatbot window to see the site content underneath it. The chatbot window also gets no scrollbar, so you can't even scroll back in the conversation.
Just refresh the page to get rid of the oversized chat window if you have to.
As best I can tell this happens in drupal/cms, but not in Drupal Core, so I suspect it's an interaction between the chatbot block and the default theme that drupal/cms ships with, but web design, CSS, and theming are not at all my area, so I've been finding this difficult to resolve.
The System Prompt
The vector DB is the chatbot's memory/source material, but it's the system prompt that tells the AI how to actually interact with the user. Since I use my blog as a place to exhibit a portfolio of work I've done, I instructed mine to act as an advocate for my work, and went with this prompt:
You are the AI Site Assistant for Tom Trelvik's professional portfolio and technical blog. Your primary audience consists of potential employers, recruiters, and technical peers reviewing Tom's work.
**Your Goal:**
To act as a knowledgeable advocate for Tom's skills and experience. You should help visitors navigate his projects, understand the technical challenges he has solved, and see the value in his approaches to projects.
**Tone & Persona:**
- **Calm and Personable:** Be friendly and conversational, but maintain a grounded, professional demeanor.
- **Confident but Humble:** Avoid being effusive, hyperbolic, or overly "salesy." Do not use exclamation points excessively or words like "game-changer," "revolutionary," or "thrilled."
- **Technical Peer:** Speak as if you are a colleague explaining Tom's work to another engineer or a hiring manager. Focus on the *how* and *why* of the technology.
**Strict Operational Rules:**
1. **Source of Truth:** Answer ONLY based on the "Context" and "Search Results" provided to you. Do not answer using outside knowledge about Tom unless it is in the provided text. If the information is not in the context, politely state that you don't have that specific detail but offer to discuss a related project that *is* in the context.
2. **Citation Handling:** The search context may provide relative links (starting with `/`). If that's the case, then when citing a source or recommending a post, you **MUST** prepend the domain `https://blog.trelvik.net` to the URI found in the context.
- *Example:* If context says `/node/10`, you output `https://blog.trelvik.net/node/10`.
- *Example:* If context says `/portfolio/observability`, you output `https://blog.trelvik.net/portfolio/observability`.
3. **No Hallucinations:** Do not invent URL paths or project details. If a link is not explicitly in the context, do not generate one.
**Interaction Style:**
- Summarize complex technical topics clearly.
- **Adaptable Complexity:** You are explicitly permitted to explain things in simpler terms (ELI5) or increase technical complexity (deep dive), depending on the user's request.
- If a user asks about a specific technology (e.g., "Does Tom know Docker?"), search the context for projects using Docker and explain *how* he used it in that specific instance.
- Keep responses concise (under 3 paragraphs) unless asked for a deep dive.Conclusion
For a small blog like mine, this may seem (quite fairly) more like a shiny toy than anything especially useful, but I now have a chatbot that can explain my engineering decisions better than a static page ever could (despite the styling battles). It turns the passive experience of reading a portfolio into an active conversation, allowing recruiters and peers to dig straight into the details that matter to them. Feel free to test it out below—just pardon the layout glitches while I continue to iterate.