Spaces:
Running
Running
| import gradio as gr | |
| from openai import AzureOpenAI | |
| import os | |
| import requests | |
| import base64 | |
| from dotenv import load_dotenv | |
| from urllib.parse import urlparse | |
| # Load environment variables from .env file | |
| load_dotenv() | |
| # Initialize Azure OpenAI client | |
| def get_openai_client(): | |
| try: | |
| return AzureOpenAI( | |
| api_key=os.getenv('AZURE_OPENAI_API_KEY').strip(), | |
| api_version=os.getenv('AZURE_OPENAI_API_VERSION').strip(), | |
| azure_endpoint=os.getenv('AZURE_OPENAI_ENDPOINT').strip(), | |
| ) | |
| except Exception as e: | |
| print(f"Failed to initialize OpenAI client: {e}") | |
| return None | |
| # Expanded list of important files that usually hold project logic | |
| important_files = [ | |
| # Documentation | |
| "README.md", "README.rst", | |
| # Python backends | |
| "app.py", "main.py", "server.py", "bot.py", "manage.py", | |
| "config.py", "settings.py", "routes.py", | |
| # Node.js / Express | |
| "index.js", "server.js", "app.js", | |
| # React / Next.js | |
| "App.tsx", "page.tsx", "index.tsx", "_app.tsx", "_document.tsx", | |
| # Angular / Vue | |
| "main.ts", "app.component.ts", "App.vue", | |
| # ML/AI Core | |
| "model.py", "train.py", "predict.py", "inference.py", | |
| # Setup / Environment | |
| "requirements.txt", "package.json", "pyproject.toml", | |
| "setup.py", "Dockerfile", ".env.example" | |
| ] | |
| def fetch_repo_files(repo_url): | |
| """ | |
| Fetch important files from a public GitHub repo. | |
| """ | |
| try: | |
| parsed = urlparse(repo_url) | |
| path_parts = parsed.path.strip("/").split("/") | |
| if len(path_parts) < 2: | |
| return None | |
| owner, repo = path_parts[0], path_parts[1].replace(".git", "") | |
| api_url = f"https://api.github.com/repos/{owner}/{repo}/contents" | |
| repo_content = {} | |
| for file in important_files: | |
| file_url = f"{api_url}/{file}" | |
| resp = requests.get(file_url) | |
| if resp.status_code == 200: | |
| data = resp.json() | |
| if data.get("encoding") == "base64": | |
| content = base64.b64decode(data["content"]).decode("utf-8", errors="ignore") | |
| else: | |
| content = data.get("content", "") | |
| repo_content[file] = content | |
| return repo_content if repo_content else None | |
| except Exception as e: | |
| print(f"[ERROR] Failed to fetch repo files: {e}") | |
| return None | |
| def generate_post(topic, tone="Professional"): | |
| try: | |
| client = get_openai_client() | |
| if not client: | |
| return "❌ OpenAI client initialization failed. Check API settings." | |
| if not topic: | |
| return "⚠️ Please provide a topic or GitHub repo link." | |
| # Check if topic is a GitHub repo link | |
| repo_content = None | |
| if topic.startswith("http") and "github.com" in topic: | |
| repo_content = fetch_repo_files(topic) | |
| if repo_content: | |
| combined_summary = "\n\n".join( | |
| [f"--- {fname} ---\n{content}" for fname, content in repo_content.items()] | |
| ) | |
| prompt = ( | |
| f"Write a {tone.lower()} LinkedIn post summarizing the following GitHub project.\n\n" | |
| f"Focus on the purpose, tech stack, and innovation:\n\n{combined_summary}" | |
| ) | |
| else: | |
| prompt = f"Write a {tone.lower()} LinkedIn post about: {topic}" | |
| messages = [ | |
| {"role": "system", "content": "You are a professional LinkedIn post writer."}, | |
| {"role": "user", "content": prompt} | |
| ] | |
| response = client.chat.completions.create( | |
| model=os.getenv('AZURE_OPENAI_DEPLOYMENT'), | |
| messages=messages, | |
| max_tokens=1000, | |
| temperature=0.9, | |
| top_p=1, | |
| frequency_penalty=0, | |
| presence_penalty=0 | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}" | |
| # Build Gradio interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🚀 LinkedIn Post Generator\nGenerate professional LinkedIn posts powered by Azure OpenAI.\n\nPaste a **topic** or a **GitHub repo link**.") | |
| with gr.Row(): | |
| topic_input = gr.Textbox(label="Topic or GitHub Repo Link", placeholder="Enter project topic or GitHub repo link...") | |
| tone_input = gr.Dropdown( | |
| ["Professional", "Casual", "Excited", "Thoughtful", "Inspirational"], | |
| value="Professional", | |
| label="Tone" | |
| ) | |
| output = gr.Textbox(label="Generated LinkedIn Post", lines=15) | |
| generate_btn = gr.Button("✨ Generate Post") | |
| generate_btn.click(fn=generate_post, inputs=[topic_input, tone_input], outputs=output) | |
| # Run app | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860, share=False, pwa=True) | |