ِAkramtaha98
Add multilingual RAG chatbot
51168f3
Raw
History Blame Contribute Delete
5.4 kB
"""
Gradio Blocks UI for the multilingual RAG chatbot.
Run: python3 app.py
"""
import subprocess
import pathlib
import gradio as gr
from rag_pipeline import RAGPipeline
if not pathlib.Path("faiss_index").exists():
print("FAISS index not found β€” running ingest.py...")
subprocess.run(["python3", "ingest.py"], check=True)
pipeline = RAGPipeline()
DESCRIPTION = """
# 🌐 Multilingual RAG Chatbot
Ask questions in **English**, **Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ© (Arabic)**, or **Bahasa Melayu (Malay)**.
Answers are grounded in the knowledge base. Retrieved source passages appear below each answer.
"""
EXAMPLES = [
["What is retrieval-augmented generation?"],
["How does machine learning differ from deep learning?"],
["What are vector databases used for?"],
["Ω…Ψ§ Ω‡Ωˆ Ψ§Ω„Ψ°ΩƒΨ§Ψ‘ Ψ§Ω„Ψ§Ψ΅Ψ·Ω†Ψ§ΨΉΩŠΨŸ"],
["ΩƒΩŠΩ ΩŠΨΉΩ…Ω„ Ψ§Ω„ΨͺΨΉΩ„Ω… Ψ§Ω„Ψ’Ω„ΩŠΨŸ"],
["Ω…Ψ§ Ω‡ΩŠ Ω‚ΩˆΨ§ΨΉΨ― Ψ§Ω„Ψ¨ΩŠΨ§Ω†Ψ§Ψͺ Ψ§Ω„Ω…ΨͺΨ¬Ω‡ΩŠΨ©ΨŸ"],
["Apakah itu kecerdasan buatan?"],
["Bagaimana pembelajaran mesin berfungsi?"],
["Apakah RAG dan kegunaannya?"],
]
RTL_CSS = """
.message-bubble p, .message-bubble span, .prose p {
unicode-bidi: plaintext;
text-align: start;
}
[lang="ar"], .rtl-text {
direction: rtl;
text-align: right;
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
}
.source-box {
border-left: 3px solid #6366f1;
padding-left: 0.75rem;
margin: 0.5rem 0;
font-size: 0.875rem;
}
.example-btn { font-size: 0.82rem !important; }
"""
JS_RTL = """
function applyRTL() {
document.querySelectorAll('.message-bubble p, .prose p').forEach(el => {
if (/[Ψ€-ΫΏ]/.test(el.innerText || '')) {
el.setAttribute('dir', 'rtl');
el.style.textAlign = 'right';
}
});
}
const observer = new MutationObserver(applyRTL);
observer.observe(document.body, { childList: true, subtree: true });
applyRTL();
"""
def format_sources(sources: list[dict]) -> str:
if not sources:
return "_No sources retrieved._"
lines = []
for i, s in enumerate(sources, 1):
snippet = s["content"].replace("\n", " ").strip()
if len(snippet) > 300:
snippet = snippet[:300] + "…"
file_name = s["source"].split("/")[-1]
lines.append(f"**[{i}] `{file_name}`**\n> {snippet}")
return "\n\n".join(lines)
def respond(message: str, history: list):
if not message.strip():
yield history, "_Please enter a question._"
return
result = pipeline.ask(message)
answer = result["answer"]
sources_md = format_sources(result["sources"])
history = history + [
{"role": "user", "content": message},
{"role": "assistant", "content": answer},
]
yield history, sources_md
def clear_all():
pipeline.chain.memory.clear()
return [], "_Sources will appear here after your first question._"
with gr.Blocks(title="Multilingual RAG Chatbot") as demo:
gr.Markdown(DESCRIPTION)
with gr.Row():
with gr.Column(scale=3):
chatbot = gr.Chatbot(
elem_id="chatbot",
label="Chat",
height=480,
)
with gr.Row():
msg_box = gr.Textbox(
placeholder="Type your question in English, Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ©, or Bahasa Melayu…",
show_label=False,
scale=8,
autofocus=True,
)
send_btn = gr.Button("Send ➀", variant="primary", scale=1)
with gr.Row():
clear_btn = gr.Button("πŸ—‘ Clear Chat", variant="secondary", size="sm")
with gr.Column(scale=2):
gr.Markdown("### πŸ“„ Retrieved Sources")
sources_box = gr.Markdown(
value="_Sources will appear here after your first question._",
)
with gr.Accordion("πŸ’‘ Example Questions", open=True):
with gr.Row():
with gr.Column():
gr.Markdown("**πŸ‡¬πŸ‡§ English**")
for ex in EXAMPLES[:3]:
gr.Button(ex[0], elem_classes="example-btn").click(
fn=lambda q=ex[0]: q,
outputs=msg_box,
)
with gr.Column():
gr.Markdown("**πŸ‡ΈπŸ‡¦ Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ©**")
for ex in EXAMPLES[3:6]:
gr.Button(ex[0], elem_classes="example-btn").click(
fn=lambda q=ex[0]: q,
outputs=msg_box,
)
with gr.Column():
gr.Markdown("**πŸ‡²πŸ‡Ύ Bahasa Melayu**")
for ex in EXAMPLES[6:]:
gr.Button(ex[0], elem_classes="example-btn").click(
fn=lambda q=ex[0]: q,
outputs=msg_box,
)
submit_inputs = [msg_box, chatbot]
submit_outputs = [chatbot, sources_box]
msg_box.submit(respond, submit_inputs, submit_outputs).then(
fn=lambda: "", outputs=msg_box
)
send_btn.click(respond, submit_inputs, submit_outputs).then(
fn=lambda: "", outputs=msg_box
)
clear_btn.click(clear_all, outputs=[chatbot, sources_box])
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
show_error=True,
css=RTL_CSS,
js=JS_RTL,
)