|
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 |