Team Ai
Apppublic

shrushhtijadhav/codingagent

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
1likes
app.py240 linesDownload Raw Back to root
1import gradio as gr2from sentence_transformers import SentenceTransformer3from sklearn.metrics.pairwise import cosine_similarity4import PyPDF25import requests6import os7from dotenv import load_dotenv8import uuid9 10# Load environment variables from .env file11load_dotenv()12 13# Load embedding model14embedder = SentenceTransformer("all-MiniLM-L6-v2")15 16# Get Gemini API key from environment variable17GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")18GEMINI_ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"19 20# In-memory chat session storage: {chat_id: [(user, assistant), ...]}21chat_sessions = {}22 23def extract_pdf_text(pdf_file):24    reader = PyPDF2.PdfReader(pdf_file)25    text = ""26    for page in reader.pages:27        page_text = page.extract_text()28        if page_text:29            text += page_text + "\n"30    return text31 32def chunk_text(text, chunk_size=500):33    import re34    sentences = re.split(r'(?<=[.!?]) +', text)35    chunks = []36    current_chunk = ""37    for sentence in sentences:38        if len(current_chunk) + len(sentence) < chunk_size:39            current_chunk += " " + sentence40        else:41            chunks.append(current_chunk.strip())42            current_chunk = sentence43    if current_chunk:44        chunks.append(current_chunk.strip())45    return chunks46 47def retrieve_relevant_chunks(query, chunks, chunk_embeddings, top_k=2):48    query_embedding = embedder.encode([query])49    similarities = cosine_similarity(query_embedding, chunk_embeddings)[0]50    top_indices = similarities.argsort()[-top_k:][::-1]51    return [chunks[i] for i in top_indices]52 53def generate_gemini_response(prompt, history=None):54    # Use LLM-based summarization for history compression55    if history:56        history_text = llm_summarize_history(history, max_turns=5)57        prompt = f"{history_text}User: {prompt}\nAssistant:"58    headers = {59        "Content-Type": "application/json"60    }61    params = {62        "key": GEMINI_API_KEY63    }64    payload = {65        "contents": [66            {67                "parts": [68                    {"text": prompt}69                ]70            }71        ]72    }73    response = requests.post(GEMINI_ENDPOINT, headers=headers, params=params, json=payload)74    if response.status_code == 200:75        result = response.json()76        try:77            return result["candidates"][0]["content"]["parts"][0]["text"].strip()78        except Exception:79            return str(result)80    else:81        return f"Error: {response.status_code} - {response.text}"82 83def improved_prompt(user_query, context=None):84    # Stronger prompt for code and explanations85    base = (86        "You are an expert coding assistant. "87        "Generate correct, complete, and well-explained code for the user's request. "88        "If the user asks for code, provide the code block with an detail explanation. "89        "If you use any context, cite it. If you don't know, say 'I don't know.'\n\n"90    )91    if context:92        base += f"Context from PDF or documents:\n{context}\n\n"93    base += f"User question:\n{user_query}\n\nAssistant:"94    return base95 96def chatbot_agent(user_query, pdf_file, chat_id):97    # Get chat history for this session98    history = chat_sessions.get(chat_id, [])99    context = None100    if pdf_file is not None:101        pdf_text = extract_pdf_text(pdf_file)102        chunks = chunk_text(pdf_text)103        chunk_embeddings = embedder.encode(chunks)104        relevant_chunks = retrieve_relevant_chunks(user_query, chunks, chunk_embeddings, top_k=3)105        context = "\n".join(relevant_chunks)106    prompt = improved_prompt(user_query, context)107    answer = generate_gemini_response(prompt, history)108    # Update history109    history.append((user_query, answer))110    chat_sessions[chat_id] = history111    return history112 113def new_chat():114    chat_id = str(uuid.uuid4())115    chat_sessions[chat_id] = []116    return chat_id, [], None117 118def delete_chat(chat_id):119    if chat_id in chat_sessions:120        del chat_sessions[chat_id]121    return gr.Dropdown.update(choices=list(chat_sessions.keys()), value=None), [], None122 123def load_chat(chat_id):124    history = chat_sessions.get(chat_id, [])125    # Convert to OpenAI-style messages for gr.Chatbot with type="messages"126    messages = []127    for user, assistant in history:128        messages.append({"role": "user", "content": user})129        messages.append({"role": "assistant", "content": assistant})130    return messages131 132def llm_summarize_history(history, max_turns=5):133    """134    Uses Gemini to summarize older chat history if it exceeds max_turns.135    Keeps the last max_turns exchanges in full, summarizes the rest.136    """137    if len(history) > max_turns:138        # Prepare summary prompt for older history139        summary_prompt = (140            "Summarize the following conversation in a concise way, preserving all important facts and context:\n\n"141        )142        for user, assistant in history[:-max_turns]:143            summary_prompt += f"User: {user}\nAssistant: {assistant}\n"144        summary = generate_gemini_response(summary_prompt)145        # Keep last max_turns exchanges in full146        recent_history = history[-max_turns:]147        history_text = summary + "\n"148        for user, assistant in recent_history:149            history_text += f"User: {user}\nAssistant: {assistant}\n"150        return history_text151    else:152        # If history is short, just concatenate153        history_text = ""154        for user, assistant in history:155            history_text += f"User: {user}\nAssistant: {assistant}\n"156        return history_text157 158with gr.Blocks(title="Coding Agent & PDF Chatbot") as iface:159    gr.Markdown(160        """161        # ๐Ÿค– Coding Agent & PDF Chatbot162        - Ask coding questions or request code generation.163        - Optionally upload a PDF to ask questions about its content.164        - Manage multiple chats: create, delete, and revisit previous conversations.165        """166    )167    with gr.Row():168        with gr.Column(scale=1):169            chat_selector = gr.Dropdown(label="Select Chat", choices=[], value=None)170            new_btn = gr.Button("โž• New Chat")171            del_btn = gr.Button("๐Ÿ—‘๏ธ Delete Chat")172        with gr.Column(scale=3):173            chat = gr.Chatbot(label="Conversation", height=400, type="messages")174            pdf_input = gr.File(label="Upload a PDF (optional)", file_types=[".pdf"])175            user_input = gr.Textbox(label="Ask a coding question", lines=2)176            submit_btn = gr.Button("Send")177    state = gr.State(None)  # Holds current chat_id178 179    # New chat180    def handle_new_chat(_):181        chat_id, history, _ = new_chat()182        return (183            gr.update(choices=list(chat_sessions.keys()), value=chat_id),184            chat_id,185            []186        )187 188    new_btn.click(189        handle_new_chat,190        inputs=[chat_selector],191        outputs=[chat_selector, state, chat]192    )193 194    # Delete chat195    def handle_delete_chat(_, chat_id):196        if chat_id in chat_sessions:197            del chat_sessions[chat_id]198        return (199            gr.update(choices=list(chat_sessions.keys()), value=None),200            [],201            None202        )203 204    del_btn.click(205        handle_delete_chat,206        inputs=[chat_selector, state],207        outputs=[chat_selector, chat, state]208    )209 210    # Load chat211    chat_selector.change(212        lambda chat_id: (chat_id, load_chat(chat_id)),213        inputs=[chat_selector],214        outputs=[state, chat]215    )216 217    # Send message218    def user_message(user_input, pdf_input, chat_id):219        if not chat_id:220            chat_id, _, _ = new_chat()221        history = chatbot_agent(user_input, pdf_input, chat_id)222        # Convert to OpenAI-style messages for gr.Chatbot with type="messages"223        messages = []224        for user, assistant in history:225            messages.append({"role": "user", "content": user})226            messages.append({"role": "assistant", "content": assistant})227        return chat_id, messages228 229    submit_btn.click(230        user_message,231        inputs=[user_input, pdf_input, state],232        outputs=[state, chat]233    )234    user_input.submit(235        user_message,236        inputs=[user_input, pdf_input, state],237        outputs=[state, chat]238    )239 240iface.launch()