natabrizy commited on
Commit
94bb3aa
·
verified ·
1 Parent(s): e073b49

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +275 -0
app.py ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents import CodeAgent, Tool
2
+ import os
3
+ import time
4
+ import requests
5
+ import re
6
+ from typing import Dict, List, Optional, Any
7
+ from smolagents.models import Model
8
+ from smolagents.default_tools import DuckDuckGoSearchTool, FinalAnswerTool
9
+ from dotenv import load_dotenv
10
+ import os
11
+
12
+ from myTools.ExtractWikipediaSection import ExtractWikipediaSection
13
+ from myTools.ExtractWebContentWithSelenium import ExtractWebContentWithSelenium
14
+ from myTools.GetPlaceholderImageTool import GetPlaceholderImageTool
15
+ from myTools.GetSVG import GetSVG
16
+ from myTools.GetSVGList import GetSVGList
17
+ from myTools.GetLogo import GetLogo
18
+
19
+ load_dotenv()
20
+ api_key = os.getenv("MistralApiKey")
21
+
22
+
23
+
24
+ class ChatMessage:
25
+ def __init__(self, role: str, content: str):
26
+ self.role = role
27
+ self.content = content
28
+ self.raw = None
29
+
30
+ @classmethod
31
+ def from_dict(cls, message_dict: Dict[str, str]) -> 'ChatMessage':
32
+ return cls(role=message_dict['role'], content=message_dict['content'])
33
+
34
+ def __repr__(self):
35
+ return f"ChatMessage(role={self.role}, content={self.content})"
36
+
37
+
38
+
39
+ class MistralClient:
40
+ def __init__(self, api_key: str, api_base: str = "https://api.mistral.ai"):
41
+ self.api_key = api_key
42
+ self.api_base = api_base
43
+
44
+ def generate(self, model_id: str, messages: List[Dict[str, str]], **kwargs):
45
+ url = f"{self.api_base}/v1/chat/completions"
46
+ headers = {
47
+ "Authorization": f"Bearer {self.api_key}",
48
+ "Content-Type": "application/json"
49
+ }
50
+ data = {
51
+ "model": model_id,
52
+ "messages": messages,
53
+ "temperature": 0.7,
54
+ "max_tokens": 4096,
55
+ **kwargs
56
+ }
57
+ retries = 5
58
+ backoff = 2.0
59
+ for attempt in range(1, retries + 1):
60
+ response = requests.post(url, headers=headers, json=data)
61
+
62
+ if response.status_code == 429:
63
+ print(f"[429] Trop de requêtes - tentative {attempt}/{retries}, attente {backoff}s...")
64
+ time.sleep(backoff)
65
+ backoff *= 2
66
+ continue
67
+
68
+ try:
69
+ response.raise_for_status()
70
+ return response.json()
71
+ except requests.exceptions.HTTPError as e:
72
+ print(f"[ERREUR] HTTP {response.status_code}: {e}")
73
+ raise e
74
+
75
+ raise RuntimeError(f"Échec après {retries} tentatives (429 ou autres erreurs)")
76
+
77
+
78
+
79
+ class MistralApiModel(Model):
80
+ """A class to interact with Mistral's API for language model interaction."""
81
+
82
+ def __init__(
83
+ self,
84
+ model_id: str,
85
+ api_key: Optional[str] = None,
86
+ api_base: Optional[str] = None,
87
+ **kwargs,
88
+ ):
89
+ super().__init__(**kwargs)
90
+ self.model_id = model_id
91
+ self.api_key = api_key
92
+ self.api_base = api_base or "https://api.mistral.ai"
93
+ self.client = MistralClient(api_key=self.api_key, api_base=self.api_base)
94
+
95
+ def generate(
96
+ self,
97
+ messages: List[Dict[str, str]],
98
+ **kwargs,
99
+ ) -> ChatMessage:
100
+ return self.__call__(messages=messages, **kwargs)
101
+
102
+ def __call__(
103
+ self,
104
+ messages: List[Dict[str, str]],
105
+ stop_sequences: Optional[List[str]] = None,
106
+ **kwargs,
107
+ ) -> ChatMessage:
108
+ completion_kwargs = self._prepare_completion_kwargs(
109
+ messages=messages,
110
+ stop_sequences=stop_sequences,
111
+ **kwargs,
112
+ )
113
+
114
+ response = self.client.generate(model_id=self.model_id, **completion_kwargs)
115
+
116
+
117
+ message = ChatMessage.from_dict(response['choices'][0]['message'])
118
+ message.raw = response
119
+ usage = response.get('usage', {})
120
+ message.token_usage = type('TokenUsage', (), {
121
+ "input_tokens": usage.get("prompt_tokens", 0),
122
+ "output_tokens": usage.get("completion_tokens", 0),
123
+ "total_tokens": usage.get("total_tokens", 0)
124
+ })()
125
+ return message
126
+
127
+ class HektoreAgent:
128
+ def __init__(self):
129
+ print("Agent initialized.")
130
+
131
+ def __call__(self, section: str, brief: str, colorOne: str, colorTwo: str, language: str, company_name: str, current_html: str = "", additional_args: dict = {}) -> str:
132
+
133
+ print(f"Agent received brief : {brief}...")
134
+ print(f"Additional args received : {additional_args}...")
135
+
136
+ all_tools = [
137
+ GetPlaceholderImageTool(),
138
+ ExtractWebContentWithSelenium(),
139
+ DuckDuckGoSearchTool(),
140
+ GetSVG(),
141
+ GetSVGList(),
142
+ GetLogo(),
143
+ FinalAnswerTool()
144
+ ]
145
+ marketing_tools = [
146
+ ExtractWebContentWithSelenium(),
147
+ DuckDuckGoSearchTool(),
148
+ FinalAnswerTool()
149
+ ]
150
+
151
+ model = MistralApiModel(
152
+ model_id="codestral-2501",
153
+ api_base="https://api.mistral.ai",
154
+ api_key=api_key
155
+ )
156
+
157
+ marketing_agent = CodeAgent(
158
+ model=model,
159
+ name="MarketingSEOExpert",
160
+ description="Specialist in marketing web and SEO, generate powerful content with impact. Can't generate HTML, juste generate raw text.",
161
+ tools=marketing_tools,
162
+ additional_authorized_imports=[
163
+ "geopandas",
164
+ "plotly",
165
+ "shapely",
166
+ "json",
167
+ "pandas",
168
+ "numpy",
169
+ "time",
170
+ "openpyxl",
171
+ "pdfminer",
172
+ "pdfminer.six",
173
+ "PyPDF2",
174
+ "io",
175
+ "open",
176
+ "librosa",
177
+ "bs4",
178
+ "os",
179
+ "builtins.open",
180
+ "builtins.write",
181
+ "PyGithub",
182
+ "requests"
183
+ ],
184
+ verbosity_level=2,
185
+ #final_answer_checks=[check_reasoning],
186
+ max_steps=15,
187
+ )
188
+
189
+ manager_agent = CodeAgent(
190
+ model=model,
191
+ tools=all_tools,
192
+ #managed_agents=[marketing_agent],
193
+ additional_authorized_imports=[
194
+ "geopandas",
195
+ "plotly",
196
+ "shapely",
197
+ "json",
198
+ "pandas",
199
+ "numpy",
200
+ "time",
201
+ "openpyxl",
202
+ "pdfminer",
203
+ "pdfminer.six",
204
+ "PyPDF2",
205
+ "io",
206
+ "open",
207
+ "librosa",
208
+ "bs4",
209
+ "os",
210
+ "builtins.open",
211
+ "builtins.write",
212
+ "PyGithub",
213
+ "requests"
214
+ ],
215
+ planning_interval=10,
216
+ verbosity_level=2,
217
+ #final_answer_checks=[check_reasoning],
218
+ max_steps=100,
219
+ )
220
+
221
+
222
+
223
+ prompt = f"""
224
+ You are a professional AI website generator.
225
+ Your job is to build a rich, modern, and impressive HTML + TailwindCSS, using semantic HTML5 and responsive design.
226
+ You will build the website section by section. Only output the HTML markup for the current section.
227
+ The content text must be awesome and very very rich.
228
+ Do not output any <html>, <head>, <body>, or <!DOCTYPE> tags.
229
+ Only write the core section content.
230
+ The name or the company is : {company_name}
231
+ The website is about : {brief}
232
+ Language of the website : {language}
233
+ You are encouraged to use advanced design elements and modern layout ideas.
234
+ We need a lot of text in each section. All text must be SEO compliant. We need Call to action.
235
+ Develop this section :
236
+ {section}
237
+
238
+
239
+
240
+ **Styling and layout**:
241
+ - Use Tailwind utility classes
242
+ - Use Tailwind's `container`, `grid`, `flex`, `gap`, `rounded`, `shadow`, `text-*`, `bg-*` utilities
243
+ - Add responsive breakpoints (`sm:`, `md:`, `lg:`) where needed
244
+ - Add hover/focus/transition effects for buttons and cards
245
+ - Add a fixed header if relevant
246
+ - The CTA text must be impactful and very short
247
+ - Use these 2 colors : Primary : {colorOne} and secondary : {colorTwo}
248
+ - Don't use join in python to build multiple block in html section
249
+ - Use TailwindCSS via CDN:
250
+ `<script src="https://cdn.tailwindcss.com"></script>`
251
+ **Extras (encouraged but optional)**:
252
+ - Use Alpine.js for interactions (mobile nav, carousel, etc.)
253
+ - Add animation classes (`transition`, `duration-300`, `ease-in-out`)
254
+ - Use SVG separators or background patterns
255
+ - Include meta tags for SEO, accessibility attributes, and semantic labels
256
+ - Use real picture, no lorem ipsum.
257
+
258
+ You may use Alpine.js for dynamic UI behavior (e.g., toggles, mobile menus, tabs).
259
+ Load it via CDN:
260
+ <script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
261
+ You may use Swiper.js for testimonials or logo sliders:
262
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
263
+ <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
264
+ You may use animate.css (Animatation) for smooth animations :
265
+ <link
266
+ rel="stylesheet"
267
+ href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
268
+ />
269
+ You may use Micromodal.js (Modal) for simple modal :
270
+ <script src="https://unpkg.com/micromodal/dist/micromodal.min.js"></script>
271
+ The page should look ready to present to enterprise clients. Do not oversimplify. No `Lorem ipsum`. Write realistic, sharp content. Only output the HTML for this section. Do not include <html>, <head>, or <body>. Do not include DOCTYPE.
272
+ """
273
+
274
+ result = manager_agent.run(task=prompt, additional_args=additional_args)
275
+ return result