Welcome to Module 4 of the tutorial series: “Build an AI-powered documentation assistant with Flask & DeepSeek”. In this module, you’ll extend the functionality of your Flask app by adding an interactive AI-powered documentation search system. Users will be able to query code functionality in natural language, and the system will generate explanations using DeepSeek’s language model. You’ll also build a chatbot-like interface for real-time code understanding.
Prerequisites
- Module 3: AI-Powered docstring generation with DeepSeek and Flask – You should have a working Flask app that generates and improves docstrings using DeepSeek.
- Top up your DeepSeek account – Ensure you have at least $2 in your DeepSeek account to use the API.
Lesson 7: Implementing a natural language query system
Objective
In this lesson, you’ll use DeepSeek’s language model to interpret and explain code functionality in response to natural language queries. You’ll also handle ambiguous or incomplete queries gracefully.
Step 1: Install Flask-Limiter
To secure the API with rate limiting, install the Flask-Limiter
package.
Run the following command in your terminal:
pip install Flask-Limiter
Step 2: Create query_handler.py
This utility will handle natural language queries using DeepSeek.
File to Create: app/utils/query_handler.py
import requests from dotenv import load_dotenv import os load_dotenv() DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") def explain_code(code_snippet, query): """ Use DeepSeek LLM to explain code based on a natural language query. """ prompt = f""" The user has provided the following Python code: {code_snippet} They are asking: "{query}" Provide a clear and concise explanation of what the code does, focusing on the user's query. """ headers = { "Authorization": f"Bearer {DEEPSEEK_API_KEY}", "Content-Type": "application/json" } data = { "model": "deepseek-chat", "prompt": prompt, "max_tokens": 200, "temperature": 0.7 } response = requests.post( "https://api.deepseek.com/beta/completions", headers=headers, json=data ) if response.status_code == 200: return response.json()["choices"][0]["text"].strip() else: raise Exception(f"Failed to generate explanation: {response.status_code}")
How it works:
- Load Environment Variables: The script uses
dotenv
to load theDEEPSEEK_API_KEY
from the.env
file. - Construct a Prompt: The
explain_code
function builds a prompt that includes the user’s code snippet and their query. - Send API Request: The function sends a POST request to the DeepSeek API with the prompt and other parameters.
- Handle API Response: If the request is successful, the function returns the generated explanation. If it fails, it raises an exception.
Step 3: Update routes.py
Add a new route to handle natural language queries.
File to Update: app/routes.py
from flask import Blueprint, jsonify, request, render_template from .utils.docstring_generator import generate_docstring, improve_docstring from app.utils.github_api import fetch_repo_contents, filter_python_files, download_file_contents from app.utils.code_parser import extract_functions_and_classes, extract_function_signature, extract_class_metadata from .utils.query_handler import explain_code from flask_limiter import Limiter from flask_limiter.util import get_remote_address main_bp = Blueprint('main', __name__) # Rate limiting for API endpoints limiter = Limiter(key_func=get_remote_address) @main_bp.route('/') def home(): return render_template("index.html") @main_bp.route('/generate-docstring', methods=['POST']) def generate_docstring_route(): """ Generate a docstring for a given code snippet. """ data = request.json code_snippet = data.get("code") context = data.get("context", "") try: docstring = generate_docstring(code_snippet, context) return jsonify({"docstring": docstring}) except Exception as e: return jsonify({"error": str(e)}), 500 @main_bp.route("/fetch-repo", methods=["POST"]) def fetch_repo(): """ Fetch and display Python files from a GitHub repository. """ data = request.json owner = data.get("owner") repo = data.get("repo") try: contents = fetch_repo_contents(owner, repo) python_files = filter_python_files(contents) return jsonify({"python_files": python_files}) except Exception as e: return jsonify({"error": str(e)}), 500 @main_bp.route("/parse-file", methods=["POST"]) def parse_file(): """ Parse a Python file and extract metadata. """ data = request.json download_url = data.get("download_url") try: code = download_file_contents(download_url) functions, classes = extract_functions_and_classes(code) function_metadata = [extract_function_signature(func) for func in functions] class_metadata = [extract_class_metadata(cls) for cls in classes] return jsonify({ "functions": function_metadata, "classes": class_metadata }) except Exception as e: return jsonify({"error": str(e)}), 500 @main_bp.route("/improve-docstring", methods=["POST"]) def improve_docstring_route(): """ Improve an existing docstring. """ data = request.json existing_docstring = data.get("docstring") context = data.get("context", "") try: improved_docstring = improve_docstring(existing_docstring, context) return jsonify({"improved_docstring": improved_docstring}) except Exception as e: return jsonify({"error": str(e)}), 500 @main_bp.route("/explain-code", methods=["POST"]) @limiter.limit("10 per minute") def explain_code_route(): """ Explain code functionality based on a natural language query. """ data = request.json code_snippet = data.get("code") query = data.get("query") try: explanation = explain_code(code_snippet, query) return jsonify({"explanation": explanation}) except Exception as e: return jsonify({"error": str(e)}), 500 @main_bp.route("/chatbot", methods=["POST"]) @limiter.limit("10 per minute") # Rate limit to prevent abuse def chatbot_route(): """ Chatbot endpoint for interactive code understanding. """ data = request.json user_input = data.get("input") code_snippet = data.get("code", "") try: # Use the same explain_code utility for chatbot responses response = explain_code(code_snippet, user_input) return jsonify({"response": response}) except Exception as e: return jsonify({"error": str(e)}), 500
How it works:
- Render
index.html
: Thehome
route now renders theindex.html
template. - Extract JSON Data: The
explain_code_route
andchatbot_route
functions retrieve the JSON payload from the request usingrequest.json
. - Call
explain_code
: The function passes the code snippet and query to theexplain_code
utility. - Return Explanation: If successful, the function returns the AI-generated explanation in JSON format.
- Handle Errors: If an error occurs, the function returns a JSON error message with a 500 status code.
Step 4: Test the /explain-code
Endpoint
Start the Flask app:
Facebook Comments