A Helpline Bot for Farmers
TFIDF matches a farmer's question — in English or Hindi typed in English letters — to the right answer, and knows when to say "I'm not sure": a smart bot, built from scratch.
1Introduction
Agriculture helplines get thousands of calls, and a large share are the same few questions: how do I get my soil tested, how do I insure my crop, where can I see mandi prices, how do I check my PM-KISAN payment.
Farmers ask these questions in their own words, often mixing English and Hindi typed in English letters: "mitti ki jaanch kahan hogi", "fasal bima kaise karein". A simple menu of options does not work well for them.
This project builds a chatbot that reads a question, finds the closest of 12 common questions using TFIDF from Unit 6, and replies with its answer. Just as importantly, it says "I am not sure" when the question is not one it knows.
Zero Hunger
No Poverty
Small farmers lose money when they miss a scheme, sell below the market price or act too late on a pest. Much of the help they need already exists — the Soil Health Card, crop insurance, the Kisan Credit Card, mandi prices online — but finding it is hard. A helpline bot that answers common questions at any hour, in the farmer's own words, helps farmers earn more and grow more: SDG 1 and SDG 2.
The curriculum asks that the project be related to the Sustainable Development Goals. That link is the reason the problem is worth solving, so it belongs at the very start of the report, not tacked on at the end.
2Stage 1 — Problem Scoping
Problem scoping means understanding the problem properly before building anything. The tool for it is the 4Ws Problem Canvas: who has the problem, what the problem is, where it happens, and why solving it matters.
- Small farmers with a mobile phone
- Helpline staff who answer the same questions all day
- Common questions take up most of the helpline's time
- Farmers miss schemes and services because they cannot find the information
- Villages, often far from an agriculture office
- At any hour, including when the helpline is closed
- Farmers get correct answers quickly, in their own words
- Helpline staff have more time for hard questions
The problem statement
The four answers are then joined into one sentence, using the curriculum's problem statement template:
Farmers with a basic mobile phone, and the staff of agriculture helplines who answer the same questions many times a day.
How it is done today
A free helpline (1800-180-1551) where experts answer in local languages. Excellent, but staff time is limited and calls can wait.
The information is there, but finding the right page means knowing what to search for, often in English.
"Press 1 for insurance, 2 for loans." They only follow fixed paths and cannot understand a question typed in the farmer's own words.
Objectives
- To read 12 common questions and answers, and many ways farmers ask them
- To normalise the questions, keeping Hindi words typed in English letters
- To build one document per answer and work out TF, DF, IDF and TFIDF for every word
- To match a new question to an answer using TFIDF and cosine similarity
- To compare TFIDF with simple word overlap, on farming and off-topic questions
- To deploy it as a short chat, with a safe reply when it is not sure
📘 Revise: Stage 1 — Problem Scoping
3Stage 2 — Data Acquisition
There are two files. faq.csv holds the 12 common questions and their answers. questions.csv holds 180 ways a farmer might ask them, each labelled with the answer it needs.
The answers point to real public services — the Soil Health Card, PM Fasal Bima Yojana, the Kisan Credit Card, e-NAM, the Meghdoot app, PM-KISAN — and deliberately give no pesticide names or doses, which only an expert should advise.
The farmers' questions were written for this project, mixing English and Hindi typed in English letters as people really write. For your own project, collect questions people actually ask — at a Krishi Vigyan Kendra, or from family — with their permission, and check every answer with an expert before using it.
Features and label
The features are what the model is given. The label is the answer it has to learn to give.
| Column | Type | What it holds | Role |
|---|---|---|---|
question | text | The farmer's question — turned into tokens, then TFIDF numbers | feature |
faq_id | text | Which of the 12 answers it needs — the label | label |
question_id | text | An ID for the question | not used |
answer | text | The reply the bot gives (in faq.csv) | not used |
The first four rows of faq.csv
| faq_id | question | answer |
|---|---|---|
soil_test | How can I get my soil tested? | Take a soil sample to your nearest soil testing laboratory or Krishi Vigyan Kendra. Under the Soil Health Card scheme you get a card showing your soil's nutrients and the fertiliser it needs.
|
weather | Where can I get the weather forecast for farming? | The India Meteorological Department gives district-level weather forecasts and farm advice. The Meghdoot app shows them on your phone.
|
insurance | How do I insure my crop? | Under the Pradhan Mantri Fasal Bima Yojana you can insure your crop through your bank, a Common Service Centre or the PMFBY website, before the last date for the season.
|
pests | Insects are attacking my crop. What should I do? | First find out which pest it is. Send a photo to your Krishi Vigyan Kendra or call the Kisan Call Centre before spraying anything, and use only what they recommend.
|
The first eight rows of questions.csv
| question_id | question | faq_id |
|---|---|---|
Q16 | will it rain this week please | weather
|
Q34 | Namaste, pmfby registration process please | insurance
|
Q20 | rain forecast for my district? | weather
|
Q55 | locusts in my field?? | pests
|
Q146 | khaad kitni dalein? | fertiliser
|
Q160 | use of paddy straw please | stubble
|
Q99 | Sir, crop selling price today?? | mandi_price
|
Q165 | Sir, do not burn stubble what to do? | stubble
|
Inside faq.csv
The 12 common questions and the answer the bot gives for each. The whole file is 12 rows, 2.2 KB. It comes with the project download, and you can take the file on its own.
Inside questions.csv
Ways farmers ask the 12 questions, each labelled with the answer it needs. The whole file is 180 rows, 8.5 KB. It comes with the project download, and you can take the file on its own.
📘 Revise: Stage 2 — Data Acquisition
4Stage 3 — Data Exploration
Data exploration means getting to know the data before trusting it: fixing what is wrong with it, then drawing it to see the patterns. The charts here are what decide what the model should be.
What was wrong with the data
Everything is changed to lower case, punctuation is removed, and greetings like sir, namaste and please are stop words.
Kept — these words carry the meaning. Hindi grammar words that carry none (kaise, kahan, hai, mein) are added to the stop words, just as "how" and "where" are.
A word that is not in the vocabulary has no IDF, so it is simply ignored. This is the bot's biggest weakness, and the evaluation shows it.

The IDF of the six most common and the six rarest words across the 12 documents. IDF = log10(N / DF), where N = 12 documents and DF is how many documents contain the word.
A word like crop appears in half of the 12 documents, so it says little about which answer a question needs. A word like mandi appears in just one document, so it gets the highest IDF possible, log10(12) ≈ 1.079. A word in every document would get log10(1) = 0. This is exactly the TFIDF idea from Unit 6: words that are everywhere are worth nothing; words that are rare are worth a lot.

Rows are the 12 answers' documents; columns are the strongest word of each document. The darker the box, the higher that word's TFIDF in that document.
Each strong word is dark in one row and pale everywhere else. That is what makes matching work: a question containing one of these words is pulled firmly towards one answer. These words were found by the TFIDF arithmetic, not chosen by a person.
📘 Revise: Stage 3 — Data Exploration
5Stage 4 — Modelling
Where this model sits in the family of AI models:
Each question needs one of 12 answers, so this is classification with 12 classes. The training questions are labelled, so it is supervised learning. Because it chats with people in their own language, it is an NLP project — and a smart bot rather than a script bot.
How the model works
The labelled questions are split into 125 for training and 55 for testing. For each of the 12 answers, a document is made from its own question and answer plus all the training questions that ask for it. That gives N = 12 documents and a vocabulary of 309 words.
For every word, the program works out TF (how often it appears in each document), DF (how many documents contain it) and IDF = log10(N / DF), and multiplies TF × IDF to get the TFIDF table — exactly the method of Unit 6.
A new question is turned into TFIDF numbers in the same way, and compared with each document using cosine similarity (0 = nothing in common, 1 = the same words in the same mix). The bot replies with the answer of the most similar document — but only if the similarity is at least 0.1. Below that, it says it is not sure and gives the Kisan Call Centre number.
The simpler method it is compared with, word overlap, just counts how many words a question shares with each document.
📘 Revise: Stage 4 — Modelling
6Stage 5 — Evaluation
On 55 farming questions the bot had never seen, TFIDF found the right answer for 45 of 55 farming questions — an accuracy of 81.8 %. Word overlap did the same.
The misses are questions using words the bot has never met — a new spelling of a Hindi word, or a word like "locusts" that no training question used. A bot like this is only as good as the questions it has seen, which is why real helpline bots keep learning from new questions.
The second test matters more for a helpline. A bot that confidently gives a farming answer to "Who won the cricket match?" looks foolish, but one that gives a wrong farming answer to a real farming question can do harm. TFIDF's similarity score lets the bot tell a strong match from a weak one, so it refused 7 of 8 off-topic questions, against 4 of 8 for word overlap. Being able to say "I'm not sure" is part of what makes a smart bot trustworthy.

Left pair: the share of unseen farming questions each method matched to the right answer. Right pair: the share of off-topic questions each method refused to answer.
On farming questions the two methods do equally well, 81.8 % each. The difference is on the right. Word overlap can only refuse when a question shares no word at all, so it refused 4 of 8, and gave a farming answer to the rest. TFIDF gives every match a similarity score, so the bot can see that one shared everyday word is a weak match — it refused 7 of 8.
📘 Revise: The Confusion Matrix
7Stage 6 — Deployment
The program ends with a short chat: four questions and the bot's replies. It answers a soil question asked in Hindi, a pest question and a mandi-price question, and politely refuses a cricket question, giving the Kisan Call Centre number instead.
The comment in the code shows how to chat with it live: replace the list of questions with input(). In real use the bot would sit behind an SMS number or WhatsApp, answer the common questions at any hour, and pass everything else to a person.

For the question shown, its cosine similarity with each of the 12 answers' documents. The red dashed line is the not-sure line.
One answer stands far above the others, well past the not-sure line, so the bot answers with confidence. For an off-topic question, every bar stays short, below the line, and the bot says it is not sure instead of guessing.
📘 Revise: Stage 6 — Deployment
8Ethical concerns
An AI project is not finished when the model works. The curriculum asks three questions of every model — is it fair (bias), can it explain itself (transparency), and who answers for its mistakes (accountability). For this project:
A wrong answer about pesticides or doses could harm crops, people and the soil. So the answers point farmers to experts and official services, and the bot never names a chemical or a dose. Every answer must be checked by an agriculture expert before the bot is used.
The not-sure reply is an ethical choice, not just a technical one. A bot that always gives an answer, even a wrong one, can mislead people who trust it. Saying "I am not sure, please call the helpline" keeps a person in charge of the hard cases.
The bot understands English and Hindi in English letters. Farmers who write in Tamil, Marathi or Bengali, or in Devanagari script, would not be understood. A real bot must be built for the languages its users speak.
The organisation running the bot is responsible for its answers, and must keep them up to date — schemes and dates change.
📘 Revise: Bias, Transparency, Accountability
9Source code
The whole program — it is also in the downloads at the top of this page — in Python with pandas, NumPy and matplotlib — the three libraries of Unit 7. It is laid out as the six stages of the AI Project Cycle, one after another. Every chart on this page was drawn by it, and every number came out of running it.
# ---------------------------------------------------------------------------
# farmer_helpline.py
#
# AI project on Natural Language Processing: a helpline chatbot that reads
# a farmer's question, typed in their own words, and replies with the right
# answer from a list of 12 common questions.
#
# CBSE Class X, Artificial Intelligence (417), Part C project work.
# SDG 2 (Zero Hunger) and SDG 1 (No Poverty).
#
# It uses TFIDF, exactly as Unit 6 defines it:
# TF(W) = how many times word W appears in a document
# IDF(W) = log10( N / DF(W) ) N = number of documents,
# DF = documents containing W
# TFIDF(W) = TF(W) x IDF(W)
# Each of the 12 answers gets a "document" made of the ways farmers ask for
# it. A new question is turned into TFIDF numbers too, and the bot replies
# with the answer whose document is most similar (cosine similarity).
# If nothing is similar enough, it says so, instead of guessing.
#
# Libraries: pandas (the questions), numpy (the arithmetic), matplotlib.
# ---------------------------------------------------------------------------
# %% Stage 1 - Problem scoping
print("=" * 60)
print("A HELPLINE BOT FOR FARMERS")
print("=" * 60)
print("Who : farmers with a question and a mobile phone")
print("What : the same questions asked again and again; helplines are busy")
print("Where : villages, at any hour, in the farmer's own words")
print("Why : quick, correct answers help farmers act in time")
print()
# %% Stage 2 - Data acquisition
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
pd.set_option("display.width", 140)
pd.set_option("display.max_colwidth", 70)
faq = pd.read_csv("faq.csv")
questions = pd.read_csv("questions.csv")
print("--- Stage 2: Data acquisition ---")
print("Answers in the FAQ :", len(faq))
print("Farmers' questions (labelled) :", len(questions))
print()
print(faq[["faq_id", "question"]].to_string(index=False))
print()
# %% Stage 3 - Data exploration
print("--- Stage 3: Data exploration ---")
# Words that appear in almost every question and say nothing about the
# topic - English and Hindi alike.
stop_words = ["how", "to", "my", "i", "the", "a", "an", "is", "what", "where", "can", "do",
"in", "for", "of", "on", "at", "and", "it", "sir", "please", "tell", "namaste",
"help", "kaise", "kahan", "kya", "hai", "ka", "ki", "ke", "mein", "se", "karein",
"which", "when", "there", "any", "me", "get", "should", "will", "this", "are",
"be", "with", "after", "now", "what", "kab", "hain"]
tokens_list = []
for text in questions["question"]:
clean = ""
for ch in text.lower():
if ch.isalpha():
clean = clean + ch
else:
clean = clean + " "
tokens = []
for w in clean.split():
if w not in stop_words:
tokens.append(w)
tokens_list.append(tokens)
questions["tokens"] = tokens_list
print("Text normalisation of one question:")
print(" Original :", questions.iloc[0]["question"])
print(" Tokens :", questions.iloc[0]["tokens"])
print()
# %% Stage 4 - Modelling
print("--- Stage 4: Modelling ---")
questions = questions.sample(frac=1, random_state=4)
cut = int(len(questions) * 0.7)
train = questions[:cut]
test = questions[cut:]
print("Training questions :", len(train))
print("Testing questions :", len(test))
# One document per answer: the FAQ's own question and answer, plus all the
# training questions that ask for it.
faq_ids = list(faq["faq_id"])
documents = []
for k in range(len(faq)):
doc = []
clean = ""
for ch in (faq.iloc[k]["question"] + " " + faq.iloc[k]["answer"]).lower():
if ch.isalpha():
clean = clean + ch
else:
clean = clean + " "
for w in clean.split():
if w not in stop_words:
doc.append(w)
for tokens in train[train["faq_id"] == faq_ids[k]]["tokens"]:
doc = doc + tokens
documents.append(doc)
vocabulary = []
for doc in documents:
for w in doc:
if w not in vocabulary:
vocabulary.append(w)
N = len(documents)
print("Documents (N) :", N)
print("Words in vocabulary:", len(vocabulary))
print()
# TF: a table with one row per document and one column per word.
tf = np.zeros((N, len(vocabulary)))
for d in range(N):
for w in documents[d]:
tf[d, vocabulary.index(w)] = tf[d, vocabulary.index(w)] + 1
# DF and IDF for every word.
df_count = (tf > 0).sum(axis=0)
idf = np.log10(N / df_count)
tfidf = tf * idf
idf_table = pd.Series(idf, index=vocabulary).round(3)
print("IDF of some words (low = in many documents, high = in one):")
for w in ["crop", "farming", "water", "mandi", "bima", "keede"]:
if w in vocabulary:
print(" " + w.ljust(10), "DF =", str(df_count[vocabulary.index(w)]).rjust(2), " IDF =", idf_table[w])
print()
# Chart 1: IDF of the most and least common words.
show = pd.concat([idf_table.sort_values().head(6), idf_table.sort_values().tail(6)])
plt.figure(figsize=(7, 4.5))
plt.barh(show.index, show.values, color=["#bab0ac"] * 6 + ["#59a14f"] * 6)
plt.title("IDF: common words count for little, rare words for a lot")
plt.xlabel("IDF = log10(N / DF)")
plt.tight_layout()
plt.savefig("chart1_idf.png")
plt.close()
# Chart 2: the TFIDF table for the strongest word of each answer.
top_words = []
for d in range(N):
w = vocabulary[int(np.argmax(tfidf[d]))]
if w not in top_words:
top_words.append(w)
grid = np.zeros((N, len(top_words)))
for k in range(len(top_words)):
grid[:, k] = tfidf[:, vocabulary.index(top_words[k])]
plt.figure(figsize=(9, 5.5))
plt.imshow(grid, cmap="Greens")
plt.xticks(range(len(top_words)), top_words, rotation=45, ha="right")
plt.yticks(range(N), faq_ids)
plt.colorbar(label="TFIDF")
plt.title("TFIDF of each answer's strongest word, in every document")
plt.tight_layout()
plt.savefig("chart2_tfidf_table.png")
plt.close()
# %% Stage 5 - Evaluation
print("--- Stage 5: Evaluation ---")
threshold = 0.1 # below this similarity, the TFIDF bot admits it is not sure
# Test 1 - farming questions the bot has never seen: is the best match the
# right answer?
overlap_right = 0
tfidf_right = 0
for i in range(len(test)):
q = np.zeros(len(vocabulary))
for w in test.iloc[i]["tokens"]:
if w in vocabulary:
q[vocabulary.index(w)] = q[vocabulary.index(w)] + 1
# Model A - word overlap: the answer whose document shares the most words.
shared = ((tf > 0) * (q > 0)).sum(axis=1)
if faq_ids[int(np.argmax(shared))] == test.iloc[i]["faq_id"]:
overlap_right = overlap_right + 1
# Model B - TFIDF and cosine similarity.
qv = q * idf
sims = np.zeros(N)
if (qv ** 2).sum() > 0:
sims = (tfidf * qv).sum(axis=1) / (np.sqrt((tfidf ** 2).sum(axis=1)) * np.sqrt((qv ** 2).sum()))
if faq_ids[int(np.argmax(sims))] == test.iloc[i]["faq_id"]:
tfidf_right = tfidf_right + 1
overlap_acc = overlap_right / len(test) * 100
tfidf_acc = tfidf_right / len(test) * 100
print("Word overlap : right answer for", overlap_right, "of", len(test), "farming questions")
print("TFIDF : right answer for", tfidf_right, "of", len(test), "farming questions")
print("Accuracy of word overlap :", round(overlap_acc, 1), "%")
print("Accuracy of TFIDF :", round(tfidf_acc, 1), "%")
print()
# Test 2 - questions that are not about farming at all. A good bot should
# say "I am not sure" instead of giving a farming answer. Word overlap can
# only refuse when not a single word is shared; TFIDF refuses when the best
# similarity is below the threshold.
off_topic = ["Who won the cricket match yesterday?", "What is the capital of France?",
"My phone screen is broken", "Tell me a joke", "How to make masala tea",
"Train timings to Delhi", "Best mobile under 10000", "When is Diwali this year?"]
overlap_refused = 0
tfidf_refused = 0
print("Off-topic question words shared best TFIDF similarity")
for text in off_topic:
clean = ""
for ch in text.lower():
if ch.isalpha():
clean = clean + ch
else:
clean = clean + " "
q = np.zeros(len(vocabulary))
for w in clean.split():
if w not in stop_words and w in vocabulary:
q[vocabulary.index(w)] = q[vocabulary.index(w)] + 1
shared = ((tf > 0) * (q > 0)).sum(axis=1).max()
qv = q * idf
best = 0
if (qv ** 2).sum() > 0:
best = ((tfidf * qv).sum(axis=1) / (np.sqrt((tfidf ** 2).sum(axis=1)) * np.sqrt((qv ** 2).sum()))).max()
if shared == 0:
overlap_refused = overlap_refused + 1
if best < threshold:
tfidf_refused = tfidf_refused + 1
print(text.ljust(40), str(shared).rjust(6), str(round(best, 3)).rjust(16))
print()
print("Off-topic questions refused by word overlap :", overlap_refused, "of", len(off_topic))
print("Off-topic questions refused by TFIDF :", tfidf_refused, "of", len(off_topic))
print()
# Chart 3: the two methods on both tests.
x = np.arange(2)
plt.figure(figsize=(7.5, 4.3))
plt.bar(x - 0.2, [overlap_acc, overlap_refused / len(off_topic) * 100], width=0.4,
label="Word overlap", color="#9c9c9c")
plt.bar(x + 0.2, [tfidf_acc, tfidf_refused / len(off_topic) * 100], width=0.4,
label="TFIDF", color="#59a14f")
plt.xticks(x, ["Farming questions\nanswered correctly", "Off-topic questions\nrefused (\"not sure\")"])
plt.ylim(0, 105)
plt.ylabel("Percent")
plt.title("Answering well, and knowing when not to answer")
plt.legend()
plt.tight_layout()
plt.savefig("chart3_methods.png")
plt.close()
# %% Stage 6 - Deployment
print("--- Stage 6: Deployment ---")
# To chat with the bot yourself, replace this list with:
# chat = [input("Your question: ")]
chat = [
"Mere khet ki mitti ki jaanch karwani hai",
"Insects are eating my cotton crop, what to do?",
"What is today's onion mandi bhav in Nashik?",
"Who is the captain of the Indian cricket team?",
]
for text in chat:
clean = ""
for ch in text.lower():
if ch.isalpha():
clean = clean + ch
else:
clean = clean + " "
q = np.zeros(len(vocabulary))
for w in clean.split():
if w not in stop_words and w in vocabulary:
q[vocabulary.index(w)] = q[vocabulary.index(w)] + 1
qv = q * idf
sims = np.zeros(N)
if (qv ** 2).sum() > 0:
sims = (tfidf * qv).sum(axis=1) / (np.sqrt((tfidf ** 2).sum(axis=1)) * np.sqrt((qv ** 2).sum()))
if text == chat[2]:
third = sims.copy() # kept for chart 4
print("Farmer :", text)
if sims.max() >= threshold:
best = int(np.argmax(sims))
print("Bot :", faq.iloc[best]["answer"])
print(" (matched '" + faq_ids[best] + "', similarity " + str(round(sims.max(), 2)) + ")")
else:
print("Bot : Sorry, I am not sure. Please call the Kisan Call Centre on 1800-180-1551.")
print()
# Chart 4: how similar the third question was to each answer.
plt.figure(figsize=(7, 4.5))
plt.barh(faq_ids, third, color="#59a14f")
plt.axvline(threshold, color="#e15759", linestyle="--", label="not-sure line")
plt.title("\"" + chat[2] + "\"")
plt.xlabel("Cosine similarity with each answer's document")
plt.legend()
plt.tight_layout()
plt.savefig("chart4_one_question.png")
plt.close()The library calls it is built from
| Call | Where | What it does |
|---|---|---|
pd.read_csv() | Stage 2 | Reads the FAQ and the questions |
ch.isalpha() / split() / stop_words | Stage 3 | Text normalisation |
doc = doc + tokens | Stage 4 | Joins all the questions for one answer into one document |
np.zeros((N, words)) | Stage 4 | An empty TF table |
(tf > 0).sum(axis=0) | Stage 4 | DF: how many documents contain each word |
np.log10(N / df_count) | Stage 4 | IDF for every word |
tf * idf | Stage 4 | The TFIDF table |
(a * b).sum() / (len_a * len_b) | Stages 5, 6 | Cosine similarity |
np.argmax(sims) | Stages 5, 6 | The answer with the highest similarity |
input() | Stage 6 (comment) | How to chat with the bot yourself |
10Sample output
A real run, exactly as it appeared. Nothing below was typed by hand.
============================================================
A HELPLINE BOT FOR FARMERS
============================================================
Who : farmers with a question and a mobile phone
What : the same questions asked again and again; helplines are busy
Where : villages, at any hour, in the farmer's own words
Why : quick, correct answers help farmers act in time
--- Stage 2: Data acquisition ---
Answers in the FAQ : 12
Farmers' questions (labelled) : 180
faq_id question
soil_test How can I get my soil tested?
weather Where can I get the weather forecast for farming?
insurance How do I insure my crop?
pests Insects are attacking my crop. What should I do?
seeds Where can I buy good quality seeds?
irrigation How can I save water in irrigation?
mandi_price Where can I check mandi prices?
loan How do I get a loan for farming?
organic How can I start organic farming?
fertiliser How much fertiliser should I use?
stubble What can I do instead of burning crop stubble?
pm_kisan How do I check my PM-KISAN payment?
--- Stage 3: Data exploration ---
Text normalisation of one question:
Original : will it rain this week please
Tokens : ['rain', 'week']
--- Stage 4: Modelling ---
Training questions : 125
Testing questions : 55
Documents (N) : 12
Words in vocabulary: 309
IDF of some words (low = in many documents, high = in one):
crop DF = 6 IDF = 0.301
farming DF = 4 IDF = 0.477
water DF = 1 IDF = 1.079
mandi DF = 1 IDF = 1.079
bima DF = 1 IDF = 1.079
--- Stage 5: Evaluation ---
Word overlap : right answer for 45 of 55 farming questions
TFIDF : right answer for 45 of 55 farming questions
Accuracy of word overlap : 81.8 %
Accuracy of TFIDF : 81.8 %
Off-topic question words shared best TFIDF similarity
Who won the cricket match yesterday? 1 0.093
What is the capital of France? 0 0
My phone screen is broken 1 0.104
Tell me a joke 0 0
How to make masala tea 1 0.086
Train timings to Delhi 0 0
Best mobile under 10000 1 0.056
When is Diwali this year? 0 0
Off-topic questions refused by word overlap : 4 of 8
Off-topic questions refused by TFIDF : 7 of 8
--- Stage 6: Deployment ---
Farmer : Mere khet ki mitti ki jaanch karwani hai
Bot : Take a soil sample to your nearest soil testing laboratory or Krishi Vigyan Kendra. Under the Soil Health Card scheme you get a card showing your soil's nutrients and the fertiliser it needs.
(matched 'soil_test', similarity 0.27)
Farmer : Insects are eating my cotton crop, what to do?
Bot : First find out which pest it is. Send a photo to your Krishi Vigyan Kendra or call the Kisan Call Centre before spraying anything, and use only what they recommend.
(matched 'pests', similarity 0.33)
Farmer : What is today's onion mandi bhav in Nashik?
Bot : The e-NAM portal and Agmarknet show the prices of crops in mandis across India, updated every day.
(matched 'mandi_price', similarity 0.51)
Farmer : Who is the captain of the Indian cricket team?
Bot : Sorry, I am not sure. Please call the Kisan Call Centre on 1800-180-1551.11The same project without code
Orange can turn text into TFIDF numbers with its Bag of Words widget, and compare documents with the Distances and Neighbors widgets — the same matching this program does. The tool is Orange Data Mining (with the Text add-on).
Load questions.csv with question as the text feature and faq_id as the target.
Lowercase, remove punctuation, and filter stop words — add the Hindi ones too.
Set Term Frequency to Count and Document Frequency to IDF. This gives TFIDF.
Compare the words of one faq_id with another.
Classify the questions and read the accuracy.
Give it one new question and see which training questions are closest — the same idea as the bot's match.
📘 Revise: No-Code AI, and Orange
12Testing
Every case below was actually run, and the result is what came back. Each one gives the whole program a small input of its own.
| Test case | Expected | Actual | Result |
|---|---|---|---|
| All 12 answers are read | Answers in the FAQ : 12 | Answers in the FAQ : 12 | Pass |
| One document for each answer: N = 12 | Documents (N) : 12 | Documents (N) : 12 | Pass |
| A word in only one document gets the highest IDF, log10(12/1) | mandi DF = 1 IDF = 1.079 | mandi DF = 1 IDF = 1.079 | Pass |
| A word in many documents gets a low IDF | crop DF = 6 IDF = 0.301 | crop DF = 6 IDF = 0.301 | Pass |
| TFIDF refuses off-topic questions that word overlap would answer | Off-topic questions refused by TFIDF : 7 of 8 | Off-topic questions refused by TFIDF : 7 of 8 | Pass |
| An off-topic question gets the safe reply | Bot : Sorry, I am not sure. Please call the Kisan Call Centre on 1800-180-1551. | Bot : Sorry, I am not sure. Please call the Kisan Call Centre on 1800-180-1551. | Pass |
| Three answers with nothing in common: every testing question matched | Accuracy of TFIDF : 100.0 % | Accuracy of TFIDF : 100.0 % | Pass |
| With N = 3, a word in all three documents would get IDF log10(3/3) = 0; one in a single document gets log10(3) = 0.477 | mandi DF = 1 IDF = 0.477 | mandi DF = 1 IDF = 0.477 | Pass |
| The FAQ file is missing | FileNotFoundError: [Errno 2] No such file or directory: 'faq.csv' | FileNotFoundError: [Errno 2] No such file or directory: 'faq.csv' | Pass |
13Results, limits and what next
- Common words like crop get a low IDF; words in only one document, like mandi, get the highest, log10(12) ≈ 1.079.
- TFIDF matched 81.8 % of unseen farming questions to the right answer.
- Its misses were questions with words it had never seen — the bot is only as good as its examples.
- TFIDF refused 7 of 8 off-topic questions; word overlap refused only 4 of 8.
- A similarity score lets a bot say "I am not sure", which makes it safer to trust.
What this model cannot do
- Only 12 questions; a real helpline has hundreds
- Words it has never seen are ignored, so new spellings and new topics are missed
- English and Hindi in English letters only
- It matches whole questions; it cannot hold a conversation or ask a follow-up question
What to add next
This is where you make the project your own. Take one of these, or an idea of yours:
- Save every question the bot is not sure about, so a person can answer it and add it to the data
- Add more questions and more ways of asking each one
- Add another language you know
- Ask a follow-up question when two answers score almost the same
What you may have to learn on your own
- TF, DF, IDF and TFIDF, worked out on real documents
- Cosine similarity between a question and a document
- The difference between a script bot and a smart bot
- Using input() to make a program interactive
14Conclusion
The project built a working helpline bot from TFIDF and cosine similarity alone. It matched 81.8 % of unseen farming questions to the right answer, in English and in Hindi typed in English letters.
Its most valuable skill turned out to be refusing. Word overlap and TFIDF found the right answer equally often, but only TFIDF's similarity score let the bot see when a match was weak — so it said "I am not sure" to 7 of 8 off-topic questions instead of giving a confident wrong answer.
A bot like this does not replace the Kisan Call Centre. It answers the common questions at any hour, and sends everything else to the people who know.
15Questions for the viva
The project carries a viva voce of its own, worth 5 marks. These are the questions it is most likely to ask about this project. Try answering each one aloud before opening it.
▸What is TFIDF?
Term Frequency × Inverse Document Frequency. TF is how often a word appears in a document; IDF = log10(N / DF) is high for words in few documents. TFIDF is high for words that are frequent in one document but rare in the others.
▸Why is the IDF of a word that appears in every document zero?
Because IDF = log10(N / N) = log10(1) = 0. A word that is everywhere cannot tell documents apart.
▸What were the documents in your project?
One document for each of the 12 answers, made of its own question and answer plus all the training questions that ask for it.
▸How does your bot choose an answer?
It turns the question into TFIDF numbers and finds the document with the highest cosine similarity. If that similarity is below 0.1, it says it is not sure.
▸Is your bot a script bot or a smart bot? Why?
A smart bot, because it understands questions typed in the user's own words by learning from examples, instead of following a fixed menu.
▸Why did TFIDF do better than word overlap on off-topic questions?
Word overlap answers whenever even one word is shared. TFIDF gives a similarity score, so a single everyday word gives a weak score and the bot can refuse.
▸Why does your bot never recommend a pesticide?
A wrong recommendation could cause harm. That advice must come from an expert, so the bot sends farmers to the Krishi Vigyan Kendra or the Kisan Call Centre.
▸Which SDGs does it relate to?
SDG 2, Zero Hunger, and SDG 1, No Poverty.
16References
- Kisan Call Centre, Department of Agriculture and Farmers Welfare — 1800-180-1551
- Soil Health Card — https://soilhealth.dac.gov.in/ ; PM Fasal Bima Yojana — https://pmfby.gov.in/ ; PM-KISAN — https://pmkisan.gov.in/
- e-NAM — https://enam.gov.in/ ; Agmarknet — https://agmarknet.gov.in/
- Sparck Jones, K. (1972). A statistical interpretation of term specificity and its application in retrieval. Journal of Documentation, 28(1) — where IDF comes from.
- CBSE, Artificial Intelligence (Subject Code 417), Class X curriculum, 2026-27 — Part C, Practical and Project Work
- CBSE, Artificial Intelligence Facilitator Handbook, Class X
- pandas — https://pandas.pydata.org/docs/; NumPy — https://numpy.org/doc/; Matplotlib — https://matplotlib.org/stable/
- LambdaLab — https://www.lambdalab.in