import modal HF_SECRET_NAME = "hf-secret" MODEL_ID = "mistralai/Mistral-7B-Instruct-v0.2" image = ( modal.Image.debian_slim(python_version="3.12") .pip_install( "smolagents[toolkit]", "huggingface_hub", "transformers", "duckduckgo-search", "fastapi", "uvicorn" ) ) 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(): # from fastapi import FastAPI, HTTPException # from pydantic import BaseModel # from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel # class AgentRequest(BaseModel): # query: str # # Use DuckDuckGoSearchTool as an example tool # agent = CodeAgent( # tools=[DuckDuckGoSearchTool()], # model=HfApiModel( # model_id=MODEL_ID # ), # Uses Hugging Face Inference API with your token # stream_outputs=True # ) # app = FastAPI() # @app.post("/") # async def run_agent(req: AgentRequest): # try: # result = agent.run(req.query) # return {"result": result} # except Exception as e: # raise HTTPException(status_code=500, detail=str(e)) # return app @modal.asgi_app() def fastapi_app(): from fastapi import FastAPI, HTTPException from pydantic import BaseModel from smolagents import CodeAgent, HfApiModel import os import tempfile import shutil import subprocess from git import Repo class RepoRequest(BaseModel): repo_url: str agent = CodeAgent( model=HfApiModel(), stream_outputs=True ) app = FastAPI() def analyze_repo(repo_path): repo_summary = [] for root, dirs, files in os.walk(repo_path): # Skip hidden directories 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', '.md', '.txt', '.json', '.yaml')): file_path = os.path.join(root, file) try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read(1000) # Read first 1000 characters repo_summary.append(f" File: {file}\n Content: {content[:500]}...") except Exception as e: repo_summary.append(f" File: {file} [Error reading file]") return "\n".join(repo_summary) @app.post("/") async def generate_readme(req: RepoRequest): temp_dir = tempfile.mkdtemp() try: # Clone repository Repo.clone_from(req.repo_url, temp_dir, branch='main', depth=1) # Analyze repository repo_analysis = analyze_repo(temp_dir) # Create prompt prompt = f"""Create a comprehensive README.md for this GitHub repository based on its structure and contents: Repository Structure: {repo_analysis} The README should include: - Project description - Installation instructions - Usage examples - Contributing guidelines - License information if available Format using markdown with proper sections.""" # Generate README 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