agroadvisor-bd / app.py
Borhan72's picture
Initial commit
84a9a2a
Raw
History Blame Contribute Delete
6.29 kB
import streamlit as st
from src.retrieval import load_vectorstore, retrieve
from src.hybrid_retrieval import hybrid_retrieve
from src.generation import generate, rewrite_query
from src.language import detect_language
from src.cache import get_cached, set_cached
# โ”€โ”€ Page config โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
st.set_page_config(
page_title="AgroAdvisor BD",
page_icon="๐ŸŒพ",
layout="wide"
)
# โ”€โ”€ Load vectorstore once at startup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@st.cache_resource
def get_vectorstore():
return load_vectorstore("data/faiss_db")
vectorstore = get_vectorstore()
# โ”€โ”€ Session state init โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
if "messages" not in st.session_state:
st.session_state.messages = []
if "last_sources" not in st.session_state:
st.session_state.last_sources = []
# โ”€โ”€ Sidebar โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
with st.sidebar:
st.image("https://cdn-icons-png.flaticon.com/512/2889/2889676.png", width=80)
st.title("๐ŸŒพ AgroAdvisor BD")
st.markdown("Agricultural Disease Advisory for Bangladesh")
st.markdown("---")
try:
chunk_count = vectorstore.count()
st.metric("Knowledge Base", f"{chunk_count:,} chunks")
except Exception:
st.metric("Knowledge Base", "N/A")
st.markdown("**Languages:** ๐Ÿ‡ฌ๐Ÿ‡ง English | ๐Ÿ‡ง๐Ÿ‡ฉ เฆฌเฆพเฆ‚เฆฒเฆพ")
st.markdown("**Sources:** BRRI, IRRI, FAO, BARI, USDA, AIS")
st.markdown("---")
if st.button("๐Ÿ—‘๏ธ Clear Chat"):
st.session_state.messages = []
st.session_state.last_sources = []
st.rerun()
if st.session_state.last_sources:
st.markdown("### ๐Ÿ“„ Sources Used")
seen = set()
for chunk in st.session_state.last_sources:
if chunk.source not in seen:
seen.add(chunk.source)
display = chunk.source.replace(".pdf", "").replace("_", " ").title()
st.markdown(f"- **{display}** ({chunk.similarity_score:.0%})")
# โ”€โ”€ Main area โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
st.title("๐ŸŒพ Agricultural Disease Advisory Chatbot")
st.markdown("Ask me anything about crop diseases, symptoms, treatments, and prevention in Bangladesh.")
with st.expander("๐Ÿ“ Example questions to try"):
st.markdown("""
- What are the symptoms of rice blast disease?
- How do I treat sheath blight in rice?
- What caused the wheat blast outbreak in Bangladesh?
- เฆงเฆพเฆจเง‡เฆฐ เฆฌเงเฆฒเฆพเฆธเงเฆŸ เฆฐเง‹เฆ—เง‡เฆฐ เฆฒเฆ•เงเฆทเฆฃ เฆ•เง€?
- เฆ†เฆฒเงเฆฐ เฆฒเง‡เฆŸ เฆฌเงเฆฒเฆพเฆ‡เฆŸ เฆฐเง‹เฆ— เฆ•เง€เฆญเฆพเฆฌเง‡ เฆฆเฆฎเฆจ เฆ•เฆฐเฆฌ?
- How does temperature affect disease spread in rice?
- What fungicide is recommended for rice blast?
- เฆธเฆฐเฆฟเฆทเฆพเฆฐ เฆฐเง‹เฆ— เฆฆเฆฎเฆจเง‡ เฆ•เง€ เฆ•เฆฐเฆฌ?
""")
# โ”€โ”€ Display chat history โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# โ”€โ”€ Chat input โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
if prompt := st.chat_input("Ask about crop diseases... (English or Bengali)"):
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("assistant"):
with st.spinner("Searching knowledge base..."):
lang = detect_language(prompt)
history = st.session_state.messages[:-1]
# โ”€โ”€ Check cache first โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
cached = get_cached(prompt, lang)
if cached:
answer = cached
used_chunks = []
chunks = []
else:
# โ”€โ”€ Rewrite ambiguous queries โ”€โ”€โ”€โ”€โ”€โ”€
try:
search_query = rewrite_query(prompt, history, lang)
except Exception:
search_query = prompt
# โ”€โ”€ Hybrid retrieval โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
try:
chunks, has_reliable = hybrid_retrieve(
search_query, vectorstore, top_k=8
)
except Exception:
chunks, has_reliable = retrieve(
search_query, vectorstore, top_k=8
)
# โ”€โ”€ Generate answer โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
answer, used_chunks = generate(
query=prompt,
chunks=chunks,
has_reliable=has_reliable,
lang_code=lang,
chat_history=history
)
# โ”€โ”€ Save to cache โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
set_cached(prompt, lang, answer)
st.markdown(answer)
# โ”€โ”€ Show retrieved context โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
if chunks:
with st.expander("๐Ÿ” View retrieved context", expanded=False):
for i, chunk in enumerate(chunks):
if chunk.similarity_score >= 0.6:
color = "๐ŸŸข"
elif chunk.similarity_score >= 0.35:
color = "๐ŸŸก"
else:
color = "๐Ÿ”ด"
st.markdown(
f"{color} **Chunk {i+1}** โ€” "
f"`{chunk.source}` | Score: `{chunk.similarity_score:.3f}`"
)
st.text(
chunk.text[:300] + "..."
if len(chunk.text) > 300
else chunk.text
)
st.markdown("---")
st.session_state.messages.append({"role": "assistant", "content": answer})
st.session_state.last_sources = used_chunks
st.rerun()