--- title: Repo Summarizer emoji: πŸ“š colorFrom: blue colorTo: indigo sdk: gradio sdk_version: "6.0.2" python_version: "3.11" app_file: app.py pinned: false short_description: Summarize GitHub repos β€” purpose, tech stack, layout. --- # Repo Summarizer A FastAPI service that takes a GitHub repository URL, fetches key files (README, `main.py`, requirements, directory tree), and returns an AI-generated **summary**, **technologies** list, and **structure** description using the Anthropic Claude API. --- ## Features - **POST /summarize** β€” Accepts a GitHub repo URL and returns: - **summary** β€” Short project description (from README, `main.py`, and the 10 longest Python files). - **technologies** β€” List of technologies/dependencies (from `requirements*.txt` and file extensions in the repo). - **structure** β€” One paragraph describing the project layout (from the repo’s directory tree). - **GET /** β€” Web UI to paste a GitHub URL or local path and see the summary result (`index.html`). - **`app.py`** β€” Gradio UI with the same behavior as the HTML page (for [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces) and local runs). - **GET /health** β€” Health check (`{"status": "ok"}`). - Unified **error responses** in JSON: `{"status": "error", "message": "..."}`. - Optional **GITHUB_TOKEN** for higher GitHub API rate limits. - **Entry-point logging** via `log_entry()` (filename, line, function name) for tracing. --- ## Project structure ``` NebiusTest/ β”œβ”€β”€ main.py # FastAPI app, /summarize, /health, /, GitHub fetch, LLM calls β”œβ”€β”€ app.py # Gradio UI (Space entry point); reuses main.py summarization logic β”œβ”€β”€ logger.py # log_entry() for request/function tracing β”œβ”€β”€ constants.py # FILE_EXTENSIONS (used for repo analysis) β”œβ”€β”€ index.html # Frontend form for GitHub URL/local path β†’ summarize β”œβ”€β”€ requirement.txt # Python dependencies β”œβ”€β”€ README.md # This file └── .gitignore ``` --- ## Setup ### 1. Install dependencies ```bash pip install -r requirement.txt ``` ### 2. Environment variables | Variable | Required | Description | |----------|----------|-------------| | `ANTHROPIC_API_KEY` | Yes | API key for Anthropic (Claude). Used for all summarization. | | `GITHUB_TOKEN` | No | GitHub personal access token. Raises API rate limit (e.g. 5000/hr vs 60/hr without). | | `SSL_CERT_FILE` / `REQUESTS_CA_BUNDLE` / `SSL_CA_BUNDLE` | No | PEM path with extra CAs (e.g. corporate HTTPS inspection). Overrides the default Mozilla bundle (`certifi`) used for GitHub + Anthropic `httpx` clients. | | `HTTPX_VERIFY` | No | Set to `0`, `false`, or `no` to **disable TLS verification** (insecure; debugging only). | Example (PowerShell): ```powershell $env:ANTHROPIC_API_KEY = "sk-ant-..." $env:GITHUB_TOKEN = "ghp_..." # optional ``` ### 3. Run the server ```bash python main.py ``` Server runs at **http://127.0.0.1:8000**. Or with uvicorn: ```bash uvicorn main:app --reload --host 127.0.0.1 --port 8000 ``` ### 4. Gradio UI (`app.py`) `app.py` opens a Gradio interface that matches `index.html`: one text field for a **GitHub URL** or **local directory path**, a **Summarize** button, and sections for **Summary**, **Technologies**, and **Structure**, with errors shown at the top of the result area. Run locally after installing dependencies (including Gradio from `requirement.txt`): ```bash python app.py ``` Gradio prints a local URL in the terminal (defaults may differ by version). The underlying logic is shared with `main.py` (same GitHub vs. local detection and LLM pipeline). **Hugging Face Spaces** - Create a Space with the **Gradio** SDK and point it at this repo, or set the Space’s **App file** to `app.py` and ensure Gradio finds the global `demo` object (this project exposes `demo` at module level in `app.py`). - Add **Secrets** for `ANTHROPIC_API_KEY` (required) and optionally `GITHUB_TOKEN`, same as for the FastAPI app. - Spaces default to a `requirements.txt` file name. If your Space only sees `requirement.txt`, either add a `requirements.txt` mirroring those dependencies or configure the Space build to use `requirement.txt`. - **Local paths** only work when Gradio runs on a machine that can read that folder. On Hugging Face, use **GitHub URLs** only. --- ## API ### POST /summarize **Request body (JSON):** ```json { "github_url": "https://github.com/owner/repo" } ``` **Success response (200):** ```json { "summary": "**ProjectName** is a ...", "technologies": ["Python", "FastAPI", "httpx"], "structure": "Main code lives in `src/`, tests in `tests/`, ..." } ``` **Error response (4xx/5xx):** All errors return JSON: ```json { "status": "error", "message": "Description of what went wrong" } ``` Example: repository not found, invalid URL, no text files, or LLM/rate-limit errors. --- ## Usage ### Browser (FastAPI + `index.html`) 1. Open http://127.0.0.1:8000/ 2. Enter a GitHub repository URL or a local repository path. 3. Click **Summarize** and view summary, technologies, and structure. ### Gradio (`app.py`) 1. Run `python app.py`. 2. Open the URL shown in the terminal. 3. Enter the same kind of repository source (GitHub URL or local path) and submit. ### cURL ```bash curl -X POST http://127.0.0.1:8000/summarize \ -H "Content-Type: application/json" \ -d "{\"github_url\": \"https://github.com/psf/requests\"}" ``` ### Python client From the repo root: ```python from main import call_summarize result = call_summarize("https://github.com/psf/requests") print(result["summary"]) print(result["technologies"]) print(result["structure"]) ``` --- ## How summarization works 1. **Parse URL** β€” Extract `owner`/`repo` from the GitHub URL. 2. **Fetch repo data** (GitHub API): - Default branch and recursive file tree. - Contents of: README.md, `main.py`, the 10 longest other `.py` files, and `requirements*.txt`. 3. **Three sequential LLM calls** (to stay within Anthropic rate limits): - **Summary** β€” From README + main.py + 10 longest Python files (Claude). Used the model claude-opus-4-6, since it works better with code - **Technologies** β€” From requirements content + file extensions found in the project (`constants.FILE_EXTENSIONS`). Used the model claude-haiku-4-5 since it's liteweight and fast (the task here is pretty simple) - **Structure** β€” From the directory tree (paths list). Used the model claude-sonnet-4-6, because this was the default model and I didn't see much difference from other models, and I guess this one is best for tree of structure. 4. **Response** β€” JSON with `summary`, `technologies` (one-line array), and `structure`. --- ## Dependencies - **fastapi** β€” Web framework. - **uvicorn** β€” ASGI server. - **httpx** β€” Async HTTP client (GitHub API). - **pydantic** β€” Request/validation. - **anthropic** β€” Claude API client. - **gradio** β€” Gradio UI in `app.py` (Spaces / local). - **python-dotenv** β€” Loads `.env` for local development (used by `main.py`). - **certifi** β€” Default CA bundle for TLS (used when custom CA env vars are not set). --- ## Logging - **logger.py** provides `log_entry()`, which prints `[filename:line] Entering function_name()` for the caller. - Used at entry of main request handlers and helpers to trace execution. --- ## License Use and modify as needed for your project.