| |
| import os |
| import json |
| import requests |
| import tempfile |
| import gradio as gr |
|
|
| |
| |
| |
| GROQ_API_KEY = os.environ.get("GROQ_API_KEY") |
| GROQ_ENDPOINT = "https://api.groq.com/openai/v1/chat/completions" |
| MODEL_NAME = os.environ.get("MODEL_NAME", "llama-3.1-8b-instant") |
|
|
| |
| |
| |
| CSS = """ |
| #business-input textarea { |
| border: 1px solid #CCCCCC; |
| } |
| #business-input textarea:focus { |
| border-color: #1E90FF; |
| } |
| #generate-btn { |
| background-color: #1E90FF; |
| color: white; |
| } |
| #generate-btn:hover { |
| background-color: #1C86EE; |
| } |
| #problems-card, #solutions-card, #explanation-card, #prompt-card { |
| padding: 15px; |
| border-radius: 8px; |
| margin-top: 10px; |
| } |
| #problems-card { |
| background-color: #F0F8FF; |
| } |
| #solutions-card { |
| background-color: #E6F7FF; |
| } |
| #explanation-card { |
| background-color: #FFFFFF; |
| } |
| #prompt-card { |
| background-color: #F5F5F5; |
| } |
| #download-btn { |
| margin-top: 10px; |
| } |
| """ |
|
|
| |
| |
| |
| def call_groq(business_name: str) -> dict: |
| """ |
| Calls the Groq API and returns a dict with keys: |
| problems, solutions, explanation, eos_prompt. |
| """ |
| if not GROQ_API_KEY: |
| raise RuntimeError("GROQ_API_KEY not set in environment") |
|
|
| user_prompt = f"""Eres un analista de negocios experto. Dado el nombre del negocio "{business_name}", haz una lista de los 5 problemas clasicos principales, propone una solucion para cada uno, ofrece una explicacion detallada combinada y, por ultimo, genera un prompt de EOS listo para usar. |
| |
| Toda la respuesta debe estar redactada en español, pero estructurada estrictamente en el siguiente formato JSON (manteniendo las claves en ingles para la lectura del sistema): |
| {{ |
| "problems": ["...", "...", "..."], |
| "solutions": ["...", "...", "..."], |
| "explanation": "...", |
| "eos_prompt": "Titulo: ...\\nContexto: ...\\nInstrucciones: ..." |
| }} |
| Devuelve unica y exclusivamente el objeto JSON, sin texto introductorio ni conclusiones.""" |
| payload = { |
| "model": MODEL_NAME, |
| "messages": [{"role": "user", "content": user_prompt}], |
| "temperature": 0.7, |
| "max_tokens": 1024, |
| } |
| headers = { |
| "Authorization": f"Bearer {GROQ_API_KEY}", |
| "Content-Type": "application/json", |
| } |
|
|
| response = requests.post( |
| GROQ_ENDPOINT, |
| headers=headers, |
| json=payload, |
| timeout=30, |
| ) |
| response.raise_for_status() |
| data = response.json() |
| content = data["choices"][0]["message"]["content"].strip() |
|
|
| |
| backticks = "\x60\x60\x60" |
| if content.startswith(backticks): |
| parts = content.split(backticks) |
| if len(parts) >= 3: |
| content = parts[1] |
| if content.lstrip().startswith("json"): |
| content = content.lstrip()[4:] |
| content = content.strip() |
|
|
| return json.loads(content) |
|
|
|
|
| def format_markdown_list(items): |
| return "\n".join([f"{i+1}. {item}" for i, item in enumerate(items)]) |
|
|
|
|
| def generate(business_name): |
| if not business_name or not business_name.strip(): |
| err_md = "### Error: El nombre del negocio no puede estar vacio." |
| return err_md, err_md, err_md, err_md, None |
|
|
| try: |
| result = call_groq(business_name.strip()) |
| problems = result.get("problems", []) |
| solutions = result.get("solutions", []) |
| explanation = result.get("explanation", "") |
| eos_prompt = result.get("eos_prompt", "") |
|
|
| if not (problems and solutions and explanation and eos_prompt): |
| raise ValueError("Respuesta incompleta del modelo.") |
|
|
| problems_md = f"### Problemas\n{format_markdown_list(problems)}" |
| solutions_md = f"### Soluciones\n{format_markdown_list(solutions)}" |
| explanation_md = f"### Explicacion\n{explanation}" |
| eos_prompt_code = eos_prompt |
|
|
| export_dict = { |
| "business_name": business_name.strip(), |
| "problems": problems, |
| "solutions": solutions, |
| "explanation": explanation, |
| "eos_prompt": eos_prompt, |
| } |
|
|
| tmp_file = tempfile.NamedTemporaryFile( |
| delete=False, suffix=".json", mode="w", encoding="utf-8" |
| ) |
| json.dump(export_dict, tmp_file, ensure_ascii=False, indent=2) |
| tmp_file.close() |
|
|
| return problems_md, solutions_md, explanation_md, eos_prompt_code, tmp_file.name |
|
|
| except requests.exceptions.Timeout: |
| err_md = "### Error: Tiempo de espera agotado. Intenta de nuevo." |
| return err_md, err_md, err_md, err_md, None |
| except requests.exceptions.RequestException as e: |
| err_md = f"### Error al conectar con Groq: {e}" |
| return err_md, err_md, err_md, err_md, None |
| except (json.JSONDecodeError, ValueError) as e: |
| err_md = f"### Error al procesar la respuesta: {e}" |
| return err_md, err_md, err_md, err_md, None |
| except Exception as e: |
| err_md = f"### Error inesperado: {e}" |
| return err_md, err_md, err_md, err_md, None |
|
|
|
|
| |
| |
| |
| with gr.Blocks() as demo: |
| gr.Markdown( |
| "<h1 style='text-align:center; font-family:Roboto; font-weight:bold; font-size:24px;'>" |
| "Analizador de Problemas de Negocio</h1>" |
| ) |
|
|
| with gr.Row(): |
| business_input = gr.Textbox( |
| label="Nombre del negocio", |
| placeholder="Introduce el nombre del negocio", |
| lines=1, |
| max_lines=1, |
| elem_id="business-input", |
| ) |
| generate_btn = gr.Button( |
| "Generar", |
| variant="primary", |
| elem_id="generate-btn", |
| ) |
|
|
| with gr.Column(): |
| problems_out = gr.Markdown(elem_id="problems-card") |
| solutions_out = gr.Markdown(elem_id="solutions-card") |
| explanation_out = gr.Markdown(elem_id="explanation-card") |
| eos_prompt_out = gr.Code( |
| label="Prompt EOS", |
| language="markdown", |
| elem_id="prompt-card", |
| ) |
| download_btn = gr.DownloadButton( |
| label="Descargar JSON", |
| value=None, |
| elem_id="download-btn", |
| ) |
|
|
| gr.Markdown( |
| "<small>Mas informacion: " |
| "<a href='https://console.groq.com/docs' target='_blank'>Documentacion Groq</a></small>", |
| elem_id="footer", |
| ) |
|
|
| generate_btn.click( |
| fn=generate, |
| inputs=[business_input], |
| outputs=[problems_out, solutions_out, explanation_out, eos_prompt_out, download_btn], |
| ) |
|
|
| |
| demo.launch(theme=gr.themes.Soft(), css=CSS) |