File size: 7,171 Bytes
9307481
 
 
389708a
35b6249
9307481
 
 
e1d773b
9307481
 
5a5228b
e9ce6d5
226df90
 
1e9170c
226df90
 
e9ce6d5
 
 
 
 
226df90
e9ce6d5
226df90
 
 
e9ce6d5
226df90
 
e9ce6d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226df90
9307481
 
e9ce6d5
9307481
e9ce6d5
9307481
e9ce6d5
 
9307481
e1d773b
e9ce6d5
 
35b6249
e9ce6d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1d773b
 
e9ce6d5
e1d773b
e9ce6d5
 
 
 
 
 
 
e1d773b
 
e9ce6d5
 
3d1b46f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# -*- coding: utf-8 -*-
import os
import json
import requests
import tempfile
import gradio as gr

# ----------------------------------------------------------------------
# Configuration
# ----------------------------------------------------------------------
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 (will be passed to demo.launch)
# ----------------------------------------------------------------------
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;
}
"""

# ----------------------------------------------------------------------
# Helper functions
# ----------------------------------------------------------------------
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()

    # Remove possible markdown fences
    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


# ----------------------------------------------------------------------
# Gradio Interface
# ----------------------------------------------------------------------
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],
    )

# Launch with theme and css inside launch as required by the platform
demo.launch(theme=gr.themes.Soft(), css=CSS)