How I build AI FAQ ChatBot under 24 hours
TL;DR;
I'm keeping up with the latest trends by developing an AI Chat App that can find answers to your questions based on a mock FAQ dataset generated by AI. Give it a try!
The source code is available on GitHub. Check out how I implemented it, and feedback is welcome.
AI AI AI
AI is a huge topic nowadays, and it looks like it's not just another buzzword, as its growth has been exponential and it has a proven record of reducing workload across various domains, such as:
- Software Development: I can't imagine life before when I started learning coding myself using a PHP4 paper book (yes, I'm that old). Nowadays, we have GitHub Co-pilot, Codium, and many more AI tools built into code editors.
- Art Direction & Graphic Generation: Tools like Midjourney, Leonado, PlaygroundAI, Davinci, Dall-E, and numerous Generative AI platforms help us save time by visualizing concepts based on simple prompts.
- Business Idea Generation: AI models now scrape data from across the web like spiders, making AI the broadest tool in this galaxy. With a specific prompt, they can help us generate business ideas that make sense for validation or implementation.
We could discuss AI's use cases all day; it's clear that AI has become an integral part of our lives.
However, with vast amounts of data in its memory and sometimes ambiguous contexts, AI can make mistakes when generating content.
But with the simple context we provide, AI could be a great fit for finding the best possible answer based on the user prompt, as it understands natural language well (proved by its ability to help me correct grammar in all blog posts).
AI FAQ
Enough with the background, let's dive into the work. During my career break, I've been craving development. Today, I built an AI FAQ Chat App based on ChatGPT with the following requirements:
- The AI understands FAQs and provides answers only from a predefined list.
- Users can prompt in any language; the app will translate the user prompt, interpret the natural language, and find the best-matched answer based on the question.
- Answers are provided in the user's language.
- Recent visitors can access their chat history.
- The app supports mobile devices; it works well on larger screens.
- Zero maintenance.
Choosing App Framework
Since my requirement is zero maintenance, I've opted to use a serverless architecture. For the frontend framework, I've selected Astro as the core system, utilizing React as the frontend library, and Hono for the API side.
I chose React due to its robust library ecosystem and my familiarity with it. For instance, tanstack-router provides type-safe routing, tanstack-query optimizes async tasks, zustand manages global state, and shadcn/ui offers a ready-to-use and type-safe library.
On the API side, Hono stands out as a leading framework for serverless applications. It offers type safety, an easy-to-use API, and supports validation libraries like zod through @hono/zod-validator. Together with drizzle-orm, it's well-suited for quickly spinning up projects. Additionally, drizzle-kit simplifies the generation of migration files.
Some may wonder why I didn't choose Next.js, which can handle both frontend and server in a single framework. Personally, I'm not a fan of Next.js; I find it slower compared to other frameworks. In this project, we don't require server-side rendering (SSR), and if we did, I would still prefer Astro or Svelte over Next.js.
Another factor is my preference to use tanstack for routing and Hono for the API. I prefer not to deal with unnecessary features and potentially slower development experiences, especially since my Mac is already slow enough.
Clean Architecture
I feel a bit guilty admitting that I'm diving into Clean Architecture. My background isn't in computer science or tech-related fields; I actually graduated with a degree in Art. However, a former colleague from my time in Product Design and Front End convinced me of the tangible benefits of Clean Architecture. So, despite lacking formal training, I've started learning and implementing it in a new project. I'm finding myself drawn to this coding style and would appreciate any feedback you might have on this repo, where I'm documenting my journey.
Folder structure
I've separated the frontend and backend with different starting points. The Astro app runs from the app/ folder and serves the API via app/pages/api/[...path].ts, which forwards requests to Hono in src/server.ts.
For client-side routing, I'm using file routing with tanstack-router, which includes excellent tools for generating route files located in app/routes.
Diagram
Since this web app is open to the public for testing, authentication isn't necessary. My goal is for users of this web app to have their chat history stored in their browser, so simply storing the session in cookies will suffice.
The diagram below illustrates how the browser continuously checks if the session is still valid and renews it as needed. The session stored in the browser is used to identify the owner of the chatroom.
On the chat side, things are a bit complex. Since we aim to support international users, we require a translation service. The API will save messages and use them as AI context for querying the FAQ. Responses must be returned in the language of the user's input.
See it live
Deployment
The project was initially planned for deployment on CloudFlare Pages. However, due to compatibility issues with WinterCG, which is used in CloudFlare's runtime environment, there were numerous deployment issues (as evidenced by multiple commits attempting to resolve them, which took about half a day to sort out). Therefore, I made the decision to switch to hosting the project on Netlify instead.
Next step
I'm quite pleased with the outcome, especially considering it only took a few hours from start to deployment (despite spending a lot of time figuring out the CloudFlare incompatibility issue).
Check out my repository on GitHub; I welcome any feedback.
The WakaTime badge above might say 27 hours, but actually, 3 hours and 40 minutes were spent fixing CloudFlare incompatibility issues (I'll describe what I've learned in another blog post). So it's just under 24 hours for this project. That wows me!