| | import modal |
| |
|
| | HF_SECRET_NAME = "hf-secret" |
| | MODEL_ID = "google/gemma-3-12b-it" |
| |
|
| | image = ( |
| | modal.Image.debian_slim(python_version="3.12") |
| | .apt_install("git") |
| | .pip_install( |
| | "smolagents[toolkit]", |
| | "huggingface_hub", |
| | "transformers", |
| | "duckduckgo-search", |
| | "fastapi", |
| | "uvicorn", |
| | "GitPython" |
| | ) |
| | ) |
| |
|
| | app = modal.App("auto-readme-agent") |
| |
|
| | @app.function( |
| | image=image, |
| | gpu="A10G", |
| | secrets=[modal.Secret.from_name("hf-secret")], |
| | timeout=180, |
| | ) |
| | @modal.asgi_app() |
| | def fastapi_app(): |
| | import os |
| | import tempfile |
| | import shutil |
| |
|
| | from git import Repo |
| | from fastapi import FastAPI, HTTPException |
| | from pydantic import BaseModel |
| | from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool |
| | |
| | class RepoRequest(BaseModel): |
| | repo_url: str |
| |
|
| | agent = CodeAgent( |
| | model=HfApiModel(), |
| | tools=[], |
| | stream_outputs=True |
| | ) |
| |
|
| | app = FastAPI() |
| |
|
| | def analyze_repo(repo_path): |
| | repo_summary = [] |
| | for root, dirs, files in os.walk(repo_path): |
| | |
| | dirs[:] = [d for d in dirs if not d.startswith('.')] |
| | |
| | rel_path = os.path.relpath(root, repo_path) |
| | repo_summary.append(f"Directory: {rel_path}") |
| | |
| | for file in files: |
| | if file.endswith(('.py')): |
| | file_path = os.path.join(root, file) |
| | try: |
| | with open(file_path, 'r', encoding='utf-8') as f: |
| | content = f.read() |
| | filtered_lines = [ |
| | line for line in content.splitlines() |
| | if not ( |
| | line.strip().startswith('#') |
| | or line.strip().startswith('import') |
| | or line.strip().startswith('from') |
| | ) |
| | ] |
| | filtered_content = "\n".join(filtered_lines) |
| | repo_summary.append(f"File: {file}\n Content: {filtered_content}...") |
| | except Exception: |
| | raise f"File: {file} [Error reading file]" |
| | return "\n".join(repo_summary)[:500] |
| |
|
| | @app.post("/") |
| | async def generate_readme(req: RepoRequest): |
| | temp_dir = tempfile.mkdtemp() |
| | try: |
| | |
| | Repo.clone_from(req.repo_url, temp_dir, branch='main', depth=1) |
| | |
| | |
| | repo_analysis = analyze_repo(temp_dir) |
| |
|
| | |
| | prompt = f"""Create a comprehensive README.md for this GitHub repository based on its structure and contents. |
| | |
| | Repository Structure: |
| | {repo_analysis} |
| | |
| | It would be good if the README.md includes the following contents: |
| | - Repository name |
| | - Project description |
| | - Contributing guidelines |
| | |
| | Format using markdown with proper sections. |
| | |
| | Here is an example of the style and detail you should provide: |
| | --- |
| | # ExampleProject |
| | |
| | A Python package for advanced data analysis and visualization. |
| | |
| | ## Installation |
| | ``` |
| | pip install exampleproject |
| | ``` |
| | |
| | ## Usage |
| | ``` |
| | from exampleproject import analyze |
| | |
| | analyze('data.csv') |
| | ``` |
| | |
| | ## Contribution |
| | |
| | Contributions are welcome! Please open an issue or submit a pull request. |
| | |
| | ... |
| | """ |
| |
|
| | |
| | result = agent.run(prompt) |
| | |
| | return {"readme": result} |
| | except Exception as e: |
| | raise HTTPException(status_code=500, detail=str(e)) |
| | finally: |
| | shutil.rmtree(temp_dir, ignore_errors=True) |
| |
|
| | return app |