The problem
General AI chatbots can give confident but wrong farming advice, such as an unsafe pesticide dose. Agriculture students and young agronomists in Bangladesh need answers they can verify, in both Bangla and English.
In the earlier version of the project, the AI feature saved articles as embeddings but never used them to answer questions, and authentication and access control needed a full review.
Who it is for
The platform is designed first for agriculture students and recent graduates, then for young agronomists who can become verified experts, and for urban and rooftop growers. It has not launched yet, so it has no users.
What I built
- Articles with drafts, tags, likes, bookmarks and follows, similar to Medium.
- A question-and-answer section with voting, reputation and expert badges by topic.
- An AI advisor that answers from the platform’s articles and shows which ones it used.
- Secure sign-in, session management and password reset.
- The React web app in Bangla and English, delivered in more than 130 small pull requests.
Architecture
A layered Spring Boot application on PostgreSQL. Each article is split into chunks of about 800 tokens and stored in pgvector, together with details such as its author, category and publishing status.
Key decisions
Only reviewed content reaches the AI
Drafts and unreviewed AI answers are never used as sources. AI-generated answers to community questions are marked as unchecked until an expert confirms or corrects them, and only then become part of the AI’s knowledge.
Sessions that can actually be ended
Access tokens last 15 minutes and are checked against a stored session on every request. Refresh tokens can only be used once and are replaced each time. When a user signs out, their session really ends.
Permission checks live in the service layer
Every change to content goes through one ownership check in the service layer, so a new endpoint cannot accidentally skip it. Private data returns “not found” rather than “forbidden”, so it does not reveal that it exists.
How I solved it
The original AI feature stored articles but never used them, and the embedding model it relied on had been retired by Google. I switched to a supported model, split articles into chunks with useful metadata, and added a retrieval step before the AI answers:
return RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.topK(aiProperties.getRag().getTopK())
.similarityThreshold(aiProperties.getRag().getSimilarityThreshold())
.filterExpression(DocumentService.publishedOnly())
.build())
.queryAugmenter(blogQueryAugmenter())
.build();When an article is edited, its stored chunks are replaced, and when it is deleted they are removed. The AI never cites an article that has changed or no longer exists.
What’s next
- Move the database schema to Flyway migrations.
- Run the full application test against a real database in CI using Testcontainers.
- Add a GitHub Actions pipeline for builds, tests and secret scanning.
