import gradio as gr from src.features.translation import translate_text from src.features.summarization import summarize_text from src.features.keyword_extraction import extract_keywords from src.features.email_writer import write_email, write_cover_letter from src.features.pdf_qa import load_pdf, build_pdf_qa_graph from src.graphs.chat_graph import ChatSession chat_session = ChatSession() LANGUAGES = [ "English", "French", "Spanish", "German", "Italian", "Portuguese", "Chinese", "Japanese", "Arabic", "Hindi", "Korean", "Russian", "Dutch", "Swedish", "Turkish", "Polish", "Ukrainian", "Vietnamese", "Thai", "Indonesian" ] custom_css = """ :root { --primary: #0D9488; --primary-light: #5EEAD4; --surface: #ffffff; --surface-2: #f0fdfa; --border: #ccfbf1; --text: #134e4a; --text-muted: #6b7280; --radius: 16px; --radius-sm: 10px; --shadow: 0 4px 24px rgba(13,148,136,0.10); } body, .gradio-container { background: linear-gradient(135deg, #f0fdfa 0%, #e6fffa 100%) !important; font-family: 'Inter', 'Segoe UI', sans-serif !important; } .gradio-container { max-width: 1200px !important; margin: 0 auto !important; padding: 2rem !important; } .app-header { background: linear-gradient(135deg, #0D9488, #14B8A6); border-radius: var(--radius); padding: 2.5rem 2rem; margin-bottom: 2rem; text-align: center; color: white; box-shadow: var(--shadow); } .tab-nav { background: white !important; border-radius: var(--radius) !important; padding: 6px !important; border: 1px solid var(--border) !important; box-shadow: var(--shadow) !important; gap: 4px !important; } .tab-nav button { border-radius: var(--radius-sm) !important; border: none !important; color: var(--text-muted) !important; font-weight: 500 !important; padding: 10px 20px !important; transition: all 0.2s !important; } .tab-nav button.selected { background: linear-gradient(135deg, #0D9488, #14B8A6) !important; color: white !important; box-shadow: 0 4px 12px rgba(13,148,136,0.3) !important; } .feature-card { background: white !important; border-radius: var(--radius) !important; border: 1px solid var(--border) !important; padding: 1.5rem !important; box-shadow: var(--shadow) !important; } textarea, input[type=text], input[type=number] { border-radius: var(--radius-sm) !important; border: 1.5px solid var(--border) !important; background: var(--surface-2) !important; font-size: 14px !important; transition: border-color 0.2s !important; } textarea:focus, input:focus { border-color: var(--primary) !important; box-shadow: 0 0 0 3px rgba(13,148,136,0.15) !important; } button.primary, .gr-button-primary { background: linear-gradient(135deg, #0D9488, #14B8A6) !important; border: none !important; color: white !important; font-weight: 600 !important; border-radius: var(--radius-sm) !important; box-shadow: 0 4px 12px rgba(13,148,136,0.3) !important; } .secondary-btn { background: white !important; border: 1.5px solid var(--border) !important; border-radius: var(--radius-sm) !important; color: var(--primary) !important; font-weight: 500 !important; } .wrap { border-radius: var(--radius-sm) !important; border: 1.5px solid var(--border) !important; background: var(--surface-2) !important; } label span { font-weight: 600 !important; color: var(--text) !important; font-size: 13px !important; } .chatbot { border-radius: var(--radius) !important; border: 1px solid var(--border) !important; box-shadow: var(--shadow) !important; } .section-title { font-size: 22px !important; font-weight: 700 !important; color: var(--text) !important; margin-bottom: 4px !important; } .section-subtitle { font-size: 14px !important; color: var(--text-muted) !important; margin-bottom: 1.5rem !important; } .badge { display: inline-block; background: rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.4); border-radius: 20px; padding: 4px 14px; font-size: 12px; color: white; font-weight: 600; margin: 4px; } .upload-btn { border-radius: var(--radius-sm) !important; border: 2px dashed var(--primary-light) !important; background: var(--surface-2) !important; } input[type=range] { accent-color: var(--primary) !important; } .output-box { background: var(--surface-2) !important; border: 1.5px solid var(--border) !important; border-radius: var(--radius-sm) !important; } """ def create_app(): with gr.Blocks(title="GenAI Toolkit",css=custom_css) as app: gr.HTML("""
๐Ÿค–

GenAI Toolkit

Powered by LangChain ยท LangGraph ยท Groq LLaMA 3

๐ŸŒ Translation ๐Ÿ“ Summarization ๐Ÿ’ฌ Chat ๐Ÿ“„ PDF Q&A โœ‰๏ธ Email Writer ๐Ÿ” Keywords
""") with gr.Tabs(elem_classes="tab-nav"): # TRANSLATION with gr.Tab("๐ŸŒ Translation"): gr.HTML('

Language Translation

Translate text instantly across 20+ languages using LLaMA 3

') with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): t_input = gr.Textbox(label="Source Text", placeholder="Type or paste text to translate...", lines=8) with gr.Row(): t_src = gr.Dropdown(label="From", choices=LANGUAGES, value="English") t_tgt = gr.Dropdown(label="To", choices=LANGUAGES, value="French") t_btn = gr.Button("Translate โžœ", variant="primary") with gr.Column(scale=1, elem_classes="feature-card"): t_out = gr.Textbox(label="Translation", lines=8, interactive=False, elem_classes="output-box") gr.HTML('

โšก Powered by LLaMA 3.1 ยท Fast & accurate

') t_btn.click(fn=translate_text, inputs=[t_input, t_src, t_tgt], outputs=t_out) # SUMMARIZATION with gr.Tab("๐Ÿ“ Summarize"): gr.HTML('

Text Summarization

Condense long articles, reports, and documents into clear summaries

') with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): s_input = gr.Textbox(label="Text to Summarize", placeholder="Paste your article, report, or any long text here...", lines=12) s_mode = gr.Radio(label="Summary Style", choices=["concise", "detailed"], value="concise") s_btn = gr.Button("Summarize โœฆ", variant="primary") with gr.Column(scale=1, elem_classes="feature-card"): s_out = gr.Textbox(label="Summary", lines=12, interactive=False, elem_classes="output-box") gr.HTML('

๐Ÿ“Š Supports long documents via map-reduce chunking

') s_btn.click(fn=summarize_text, inputs=[s_input, s_mode], outputs=s_out) # KEYWORDS with gr.Tab("๐Ÿ” Keywords"): gr.HTML('

Keyword Extraction

Identify the most important topics and phrases in any text

') with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): k_input = gr.Textbox(label="Input Text", placeholder="Paste any text to extract key topics...", lines=10) k_num = gr.Slider(label="Number of Keywords", minimum=5, maximum=20, value=10, step=1) k_btn = gr.Button("Extract Keywords ๐Ÿ”", variant="primary") with gr.Column(scale=1, elem_classes="feature-card"): k_out = gr.Textbox(label="Extracted Keywords", lines=10, interactive=False, elem_classes="output-box") gr.HTML('

๐Ÿท๏ธ Returns keywords with context and relevance

') k_btn.click(fn=extract_keywords, inputs=[k_input, k_num], outputs=k_out) # EMAIL WRITER with gr.Tab("โœ‰๏ธ Email Writer"): gr.HTML('

Email & Cover Letter Writer

Generate professional emails and cover letters instantly

') with gr.Tabs(): with gr.Tab("๐Ÿ“ง Email"): with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): e_type = gr.Dropdown(label="Email Type", choices=["follow-up","introduction","apology","request","thank you","complaint","proposal","invitation"], value="follow-up") e_ctx = gr.Textbox(label="Purpose / Context", placeholder="Describe the goal of this email...", lines=4) e_tone = gr.Dropdown(label="Tone", choices=["professional","friendly","formal","casual","urgent"], value="professional") with gr.Row(): e_to = gr.Textbox(label="Recipient", placeholder="Hiring Manager") e_from = gr.Textbox(label="Your Name", placeholder="Shashank") e_btn = gr.Button("Generate Email โœ‰๏ธ", variant="primary") with gr.Column(scale=1, elem_classes="feature-card"): e_out = gr.Textbox(label="Generated Email", lines=18, interactive=False, elem_classes="output-box") e_btn.click(fn=write_email, inputs=[e_type, e_ctx, e_tone, e_to, e_from], outputs=e_out) with gr.Tab("๐Ÿ“„ Cover Letter"): with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): cl_name = gr.Textbox(label="Your Name", placeholder="Shashank Hegde") cl_job = gr.Textbox(label="Job Title Applying For", placeholder="ML Engineer") cl_co = gr.Textbox(label="Company Name", placeholder="Google DeepMind") cl_sk = gr.Textbox(label="Key Skills", placeholder="Python, LangChain, MLflow, XGBoost...", lines=3) cl_exp = gr.Textbox(label="Experience Summary", placeholder="3 years building ML pipelines...", lines=3) cl_btn = gr.Button("Generate Cover Letter ๐Ÿ“„", variant="primary") with gr.Column(scale=1, elem_classes="feature-card"): cl_out = gr.Textbox(label="Cover Letter", lines=18, interactive=False, elem_classes="output-box") cl_btn.click(fn=write_cover_letter, inputs=[cl_job, cl_co, cl_sk, cl_exp, cl_name], outputs=cl_out) # CHAT with gr.Tab("๐Ÿ’ฌ Chat"): gr.HTML('

AI Chat Assistant

Multi-turn conversations powered by LangGraph + LLaMA 3.3 70B

') with gr.Column(elem_classes="feature-card"): chatbot = gr.Chatbot(height=450, label="", elem_classes="chatbot", show_label=False,type="messages") with gr.Row(): c_input = gr.Textbox(label="", placeholder="Ask me anything...", scale=5, container=False) c_btn = gr.Button("Send โžœ", variant="primary", scale=1) with gr.Row(): c_clear = gr.Button("๐Ÿ—‘๏ธ Clear Conversation", elem_classes="secondary-btn") gr.HTML('

๐Ÿง  Maintains full conversation context via LangGraph state

') def respond(message, history): if not message.strip(): return "", history response = chat_session.chat(message) history = history or [] # history.append((message, response)) history.append({"role": "user", "content": message}) history.append({"role": "assistant", "content": response}) return "", history def clear(): chat_session.clear_history() return [] c_btn.click(fn=respond, inputs=[c_input, chatbot], outputs=[c_input, chatbot]) c_input.submit(fn=respond, inputs=[c_input, chatbot], outputs=[c_input, chatbot]) c_clear.click(fn=clear, outputs=chatbot) # PDF Q&A with gr.Tab("๐Ÿ“„ PDF Q&A"): gr.HTML('

PDF Question & Answer

Upload any PDF and ask questions โ€” powered by RAG + LangGraph

') pdf_state = gr.State("") with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="feature-card"): p_file = gr.File(label="Upload PDF", file_types=[".pdf"], elem_classes="upload-btn") p_status = gr.Textbox(label="Status", interactive=False, lines=1) p_q = gr.Textbox(label="Your Question", placeholder="What is the main topic of this document?", lines=4) p_btn = gr.Button("Ask Question ๐Ÿ”", variant="primary") gr.HTML('

๐Ÿ“š Uses FAISS vector search + semantic chunking

') with gr.Column(scale=1, elem_classes="feature-card"): p_out = gr.Textbox(label="Answer", lines=18, interactive=False, elem_classes="output-box") def load_pdf_file(file): if file is None: return "", "โš ๏ธ No file uploaded." text = load_pdf(file.name) word_count = len(text.split()) return text, f"โœ… PDF loaded โ€” {word_count:,} words extracted" def answer_pdf_question(question, pdf_text): if not pdf_text: return "โš ๏ธ Please upload a PDF first." if not question.strip(): return "โš ๏ธ Please enter a question." graph = build_pdf_qa_graph() result = graph.invoke({ "pdf_text": pdf_text, "question": question, "context": "", "answer": "" }) return result["answer"] p_file.change(fn=load_pdf_file, inputs=p_file, outputs=[pdf_state, p_status]) p_btn.click(fn=answer_pdf_question, inputs=[p_q, pdf_state], outputs=p_out) gr.HTML("""
Built with LangChain ยท LangGraph ยท Groq ยท Gradio  |  GitHub
""") return app if __name__ == "__main__": app = create_app() app.launch( server_name="0.0.0.0", server_port=7860, share=False, )