lastmass commited on
Commit
3cbc5d0
·
1 Parent(s): 05eddcd

change to Nebius API

Browse files
Files changed (3) hide show
  1. FETCH_HEAD +0 -0
  2. app.py +96 -83
  3. requirements.txt +2 -2
FETCH_HEAD ADDED
File without changes
app.py CHANGED
@@ -6,21 +6,21 @@ from PIL import Image
6
  import httpx
7
  import html
8
  from lzstring import LZString
9
- import google.generativeai as genai
 
10
 
11
  # --- 默认API配置 ---
12
- DEFAULT_GEMINI_API_KEY = ""
13
- DEFAULT_DEEPSEEK_API_KEY = ""
14
- DEEPSEEK_BASE_URL = "https://api.deepseek.com"
15
 
16
  # --- 核心工具函数 ---
17
- def analyze_image(image: Image.Image, gemini_api_key: str = "") -> str:
18
  """
19
  Analyze an uploaded image and provide a detailed description of its content and layout.
20
 
21
  Args:
22
  image: The PIL Image object to analyze
23
- gemini_api_key: Gemini API key for image analysis
24
 
25
  Returns:
26
  A detailed description of the image content, layout, and website type
@@ -29,22 +29,24 @@ def analyze_image(image: Image.Image, gemini_api_key: str = "") -> str:
29
  return "Error: No image provided"
30
 
31
  # 使用提供的API密钥或默认密钥
32
- api_key = gemini_api_key.strip() if gemini_api_key.strip() else DEFAULT_GEMINI_API_KEY
33
 
34
  if not api_key:
35
- return "Error: Gemini API key not provided"
36
 
37
  try:
38
- # 配置Gemini API
39
- genai.configure(api_key=api_key)
 
 
 
40
 
41
  # 转换图片为base64
42
  buffered = io.BytesIO()
43
  image.save(buffered, format="PNG")
44
  img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
45
 
46
- # 创建模型和提示
47
- model = genai.GenerativeModel(model_name="gemini-2.5-flash-preview-05-20")
48
  prompt = """
49
  Analyze this image and provide a concise description.
50
  Describe the main elements, colors, layout, and UI components.
@@ -52,23 +54,39 @@ def analyze_image(image: Image.Image, gemini_api_key: str = "") -> str:
52
  Focus on structural and visual elements that would be important for recreating the design.
53
  """
54
 
55
- image_part = {"mime_type": "image/png", "data": img_str}
56
- contents = [prompt, image_part]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
- # 生成描述
59
- response = model.generate_content(contents)
60
- return response.text
61
 
62
  except Exception as e:
63
  return f"Error analyzing image: {str(e)}"
64
 
65
- def generate_html_code(description: str, deepseek_api_key: str = "") -> str:
66
  """
67
  Generate HTML/CSS/JavaScript code based on a website description.
68
 
69
  Args:
70
  description: Detailed description of the website to generate
71
- deepseek_api_key: DeepSeek API key for code generation
72
 
73
  Returns:
74
  Complete HTML code with embedded CSS and JavaScript
@@ -77,10 +95,10 @@ def generate_html_code(description: str, deepseek_api_key: str = "") -> str:
77
  return "Error: Invalid or missing description"
78
 
79
  # 使用提供的API密钥或默认密钥
80
- api_key = deepseek_api_key.strip() if deepseek_api_key.strip() else DEFAULT_DEEPSEEK_API_KEY
81
 
82
  if not api_key:
83
- return "Error: DeepSeek API key not provided"
84
 
85
  prompt = f"""
86
  Generate a complete, responsive webpage based on this description:
@@ -99,46 +117,38 @@ def generate_html_code(description: str, deepseek_api_key: str = "") -> str:
99
  Return only the complete HTML code starting with <!DOCTYPE html> and ending with </html>.
100
  """
101
 
102
- headers = {
103
- "Authorization": f"Bearer {api_key}",
104
- "Content-Type": "application/json"
105
- }
106
-
107
- data = {
108
- "model": "deepseek-chat",
109
- "messages": [{"role": "user", "content": prompt}],
110
- "temperature": 0.7,
111
- "max_tokens": 8000
112
- }
113
-
114
  try:
115
- import requests
116
- response = requests.post(
117
- f"{DEEPSEEK_BASE_URL}/chat/completions",
118
- headers=headers,
119
- json=data,
120
- timeout=60
121
  )
122
 
123
- if response.status_code == 200:
124
- result = response.json()
125
- html_code = result['choices'][0]['message']['content']
126
-
127
- # 清理代码格式
128
- if html_code.strip().startswith("```html"):
129
- html_code = html_code.split("```html", 1)[1].strip()
130
- if html_code.strip().endswith("```"):
131
- html_code = html_code.rsplit("```", 1)[0].strip()
132
-
133
- # 确保代码完整性
134
- if "<!DOCTYPE html>" in html_code and "</html>" in html_code:
135
- start = html_code.find("<!DOCTYPE html>")
136
- end = html_code.rfind("</html>") + 7
137
- return html_code[start:end]
138
- else:
139
- return html_code
 
 
 
 
 
 
140
  else:
141
- return f"Error: API request failed with status {response.status_code}"
142
 
143
  except Exception as e:
144
  return f"Error generating HTML code: {str(e)}"
@@ -198,7 +208,17 @@ def create_codesandbox(html_code: str) -> str:
198
 
199
  # 尝试创建sandbox
200
  import requests
201
- response = requests.post(codesandbox_url, timeout=30)
 
 
 
 
 
 
 
 
 
 
202
 
203
  if response.status_code == 200:
204
  result = response.json()
@@ -212,33 +232,32 @@ def create_codesandbox(html_code: str) -> str:
212
  except Exception as e:
213
  return f"Error creating CodeSandbox: {str(e)}"
214
 
215
- def screenshot_to_code(image: Image.Image, gemini_api_key: str = "", deepseek_api_key: str = "") -> tuple:
216
  """
217
  Complete pipeline: analyze image and generate corresponding HTML code.
218
 
219
  Args:
220
  image: Screenshot image to analyze
221
- gemini_api_key: Gemini API key for image analysis
222
- deepseek_api_key: DeepSeek API key for code generation
223
 
224
  Returns:
225
  Tuple of (description, html_code)
226
  """
227
  # 分析图片
228
- description = analyze_image(image, gemini_api_key)
229
 
230
  if description.startswith("Error"):
231
  return description, "Error: Cannot generate code due to image analysis failure"
232
 
233
  # 生成代码
234
- html_code = generate_html_code(description, deepseek_api_key)
235
 
236
  return description, html_code
237
 
238
  # --- Gradio界面 ---
239
  with gr.Blocks(
240
  theme=gr.themes.Soft(),
241
- title="AI Website Generator - MCP Compatible",
242
  css="""
243
  .api-section { background: #f8f9fa; padding: 15px; border-radius: 8px; margin: 10px 0; }
244
  .tool-section { border: 1px solid #e0e0e0; padding: 15px; border-radius: 8px; margin: 10px 0; }
@@ -246,13 +265,13 @@ with gr.Blocks(
246
  ) as app:
247
 
248
  gr.Markdown("""
249
- # 🚀 AI Website Generator (MCP Compatible)
250
 
251
- Transform website screenshots into functional HTML code using AI.
252
 
253
  **Features:**
254
- - 📸 Image analysis with Gemini AI
255
- - 💻 HTML/CSS/JS code generation with DeepSeek
256
  - 🌐 Direct CodeSandbox deployment
257
  - 🔧 MCP (Model Context Protocol) compatible
258
 
@@ -270,17 +289,11 @@ with gr.Blocks(
270
 
271
  # API配置
272
  with gr.Group():
273
- gr.Markdown("**API Keys (Optional)**")
274
- gemini_key = gr.Textbox(
275
- label="Gemini API Key",
276
- type="password",
277
- placeholder="Leave empty to use default",
278
- value=""
279
- )
280
- deepseek_key = gr.Textbox(
281
- label="DeepSeek API Key",
282
  type="password",
283
- placeholder="Leave empty to use default",
284
  value=""
285
  )
286
 
@@ -326,21 +339,21 @@ with gr.Blocks(
326
  with gr.Column():
327
  gr.Markdown("#### 📸 Image Analysis Tool")
328
  img_tool = gr.Image(type="pil", label="Image")
329
- gemini_key_tool = gr.Textbox(label="Gemini API Key", type="password")
330
  analyze_btn = gr.Button("Analyze Image")
331
  analysis_result = gr.Textbox(label="Analysis Result", lines=5)
332
 
333
  with gr.Column():
334
  gr.Markdown("#### 💻 Code Generation Tool")
335
  desc_input = gr.Textbox(label="Description", lines=3)
336
- deepseek_key_tool = gr.Textbox(label="DeepSeek API Key", type="password")
337
  code_btn = gr.Button("Generate Code")
338
  code_result = gr.Code(label="Generated Code", language="html")
339
 
340
  # 事件绑定
341
  generate_btn.click(
342
  fn=screenshot_to_code,
343
- inputs=[image_input, gemini_key, deepseek_key],
344
  outputs=[description_output, html_output]
345
  )
346
 
@@ -352,13 +365,13 @@ with gr.Blocks(
352
 
353
  analyze_btn.click(
354
  fn=analyze_image,
355
- inputs=[img_tool, gemini_key_tool],
356
  outputs=[analysis_result]
357
  )
358
 
359
  code_btn.click(
360
  fn=generate_html_code,
361
- inputs=[desc_input, deepseek_key_tool],
362
  outputs=[code_result]
363
  )
364
 
 
6
  import httpx
7
  import html
8
  from lzstring import LZString
9
+ import os
10
+ from openai import OpenAI
11
 
12
  # --- 默认API配置 ---
13
+ DEFAULT_NEBIUS_API_KEY = "eyJhbGciOiJIUzI1NiIsImtpZCI6IlV6SXJWd1h0dnprLVRvdzlLZWstc0M1akptWXBvX1VaVkxUZlpnMDRlOFUiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiJnb29nbGUtb2F1dGgyfDEwNTA1MTQzMDg2MDMwMzIxNDEwMiIsInNjb3BlIjoib3BlbmlkIG9mZmxpbmVfYWNjZXNzIiwiaXNzIjoiYXBpX2tleV9pc3N1ZXIiLCJhdWQiOlsiaHR0cHM6Ly9uZWJpdXMtaW5mZXJlbmNlLmV1LmF1dGgwLmNvbS9hcGkvdjIvIl0sImV4cCI6MTkwNjU5ODA0NCwidXVpZCI6ImNkOGFiMWZlLTIxN2QtNDJlMy04OWUwLWM1YTg4MjcwMGVhNyIsIm5hbWUiOiJodW5nZ2luZyIsImV4cGlyZXNfYXQiOiIyMDMwLTA2LTAyVDAyOjM0OjA0KzAwMDAifQ.MA52QuIiNruK7_lX688RXAEI2TkcCOjcf_02XrpnhI8"
14
+ NEBIUS_BASE_URL = "https://api.studio.nebius.com/v1/"
 
15
 
16
  # --- 核心工具函数 ---
17
+ def analyze_image(image: Image.Image, nebius_api_key: str = "") -> str:
18
  """
19
  Analyze an uploaded image and provide a detailed description of its content and layout.
20
 
21
  Args:
22
  image: The PIL Image object to analyze
23
+ nebius_api_key: Nebius API key for image analysis
24
 
25
  Returns:
26
  A detailed description of the image content, layout, and website type
 
29
  return "Error: No image provided"
30
 
31
  # 使用提供的API密钥或默认密钥
32
+ api_key = nebius_api_key.strip() if nebius_api_key.strip() else DEFAULT_NEBIUS_API_KEY
33
 
34
  if not api_key:
35
+ return "Error: Nebius API key not provided"
36
 
37
  try:
38
+ # 配置Nebius OpenAI客户端
39
+ client = OpenAI(
40
+ base_url=NEBIUS_BASE_URL,
41
+ api_key=api_key,
42
+ )
43
 
44
  # 转换图片为base64
45
  buffered = io.BytesIO()
46
  image.save(buffered, format="PNG")
47
  img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
48
 
49
+ # 创建提示
 
50
  prompt = """
51
  Analyze this image and provide a concise description.
52
  Describe the main elements, colors, layout, and UI components.
 
54
  Focus on structural and visual elements that would be important for recreating the design.
55
  """
56
 
57
+ # 使用Qwen2.5-VL-72B-Instruct模型进行图像分析
58
+ response = client.chat.completions.create(
59
+ model="Qwen/Qwen2.5-VL-72B-Instruct",
60
+ messages=[
61
+ {
62
+ "role": "user",
63
+ "content": [
64
+ {"type": "text", "text": prompt},
65
+ {
66
+ "type": "image_url",
67
+ "image_url": {
68
+ "url": f"data:image/png;base64,{img_str}"
69
+ }
70
+ }
71
+ ]
72
+ }
73
+ ],
74
+ max_tokens=1000,
75
+ temperature=0.7
76
+ )
77
 
78
+ return response.choices[0].message.content
 
 
79
 
80
  except Exception as e:
81
  return f"Error analyzing image: {str(e)}"
82
 
83
+ def generate_html_code(description: str, nebius_api_key: str = "") -> str:
84
  """
85
  Generate HTML/CSS/JavaScript code based on a website description.
86
 
87
  Args:
88
  description: Detailed description of the website to generate
89
+ nebius_api_key: Nebius API key for code generation
90
 
91
  Returns:
92
  Complete HTML code with embedded CSS and JavaScript
 
95
  return "Error: Invalid or missing description"
96
 
97
  # 使用提供的API密钥或默认密钥
98
+ api_key = nebius_api_key.strip() if nebius_api_key.strip() else DEFAULT_NEBIUS_API_KEY
99
 
100
  if not api_key:
101
+ return "Error: Nebius API key not provided"
102
 
103
  prompt = f"""
104
  Generate a complete, responsive webpage based on this description:
 
117
  Return only the complete HTML code starting with <!DOCTYPE html> and ending with </html>.
118
  """
119
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  try:
121
+ # 配置Nebius OpenAI客户端
122
+ client = OpenAI(
123
+ base_url=NEBIUS_BASE_URL,
124
+ api_key=api_key,
 
 
125
  )
126
 
127
+ # 使用DeepSeek-V3-0324模型进行代码生成
128
+ response = client.chat.completions.create(
129
+ model="deepseek-ai/DeepSeek-V3-0324",
130
+ messages=[
131
+ {"role": "user", "content": prompt}
132
+ ],
133
+ max_tokens=8000,
134
+ temperature=0.7
135
+ )
136
+
137
+ html_code = response.choices[0].message.content
138
+
139
+ # 清理代码格式
140
+ if html_code.strip().startswith("```html"):
141
+ html_code = html_code.split("```html", 1)[1].strip()
142
+ if html_code.strip().endswith("```"):
143
+ html_code = html_code.rsplit("```", 1)[0].strip()
144
+
145
+ # 确保代码完整性
146
+ if "<!DOCTYPE html>" in html_code and "</html>" in html_code:
147
+ start = html_code.find("<!DOCTYPE html>")
148
+ end = html_code.rfind("</html>") + 7
149
+ return html_code[start:end]
150
  else:
151
+ return html_code
152
 
153
  except Exception as e:
154
  return f"Error generating HTML code: {str(e)}"
 
208
 
209
  # 尝试创建sandbox
210
  import requests
211
+
212
+ # 尝试POST请求创建sandbox
213
+ try:
214
+ response = requests.post(
215
+ "https://codesandbox.io/api/v1/sandboxes/define",
216
+ json=parameters,
217
+ timeout=10
218
+ )
219
+ except:
220
+ # 如果POST失败,返回GET URL
221
+ return codesandbox_url
222
 
223
  if response.status_code == 200:
224
  result = response.json()
 
232
  except Exception as e:
233
  return f"Error creating CodeSandbox: {str(e)}"
234
 
235
+ def screenshot_to_code(image: Image.Image, nebius_api_key: str = "") -> tuple:
236
  """
237
  Complete pipeline: analyze image and generate corresponding HTML code.
238
 
239
  Args:
240
  image: Screenshot image to analyze
241
+ nebius_api_key: Nebius API key for both image analysis and code generation
 
242
 
243
  Returns:
244
  Tuple of (description, html_code)
245
  """
246
  # 分析图片
247
+ description = analyze_image(image, nebius_api_key)
248
 
249
  if description.startswith("Error"):
250
  return description, "Error: Cannot generate code due to image analysis failure"
251
 
252
  # 生成代码
253
+ html_code = generate_html_code(description, nebius_api_key)
254
 
255
  return description, html_code
256
 
257
  # --- Gradio界面 ---
258
  with gr.Blocks(
259
  theme=gr.themes.Soft(),
260
+ title="AI Website Generator - MCP Compatible (Nebius)",
261
  css="""
262
  .api-section { background: #f8f9fa; padding: 15px; border-radius: 8px; margin: 10px 0; }
263
  .tool-section { border: 1px solid #e0e0e0; padding: 15px; border-radius: 8px; margin: 10px 0; }
 
265
  ) as app:
266
 
267
  gr.Markdown("""
268
+ # 🚀 AI Website Generator (MCP Compatible - Nebius)
269
 
270
+ Transform website screenshots into functional HTML code using Nebius AI.
271
 
272
  **Features:**
273
+ - 📸 Image analysis with Qwen2.5-VL-72B-Instruct
274
+ - 💻 HTML/CSS/JS code generation with DeepSeek-V3-0324
275
  - 🌐 Direct CodeSandbox deployment
276
  - 🔧 MCP (Model Context Protocol) compatible
277
 
 
289
 
290
  # API配置
291
  with gr.Group():
292
+ gr.Markdown("**Nebius API Key (Required)**")
293
+ nebius_key = gr.Textbox(
294
+ label="Nebius API Key",
 
 
 
 
 
 
295
  type="password",
296
+ placeholder="Enter your Nebius API key",
297
  value=""
298
  )
299
 
 
339
  with gr.Column():
340
  gr.Markdown("#### 📸 Image Analysis Tool")
341
  img_tool = gr.Image(type="pil", label="Image")
342
+ nebius_key_tool = gr.Textbox(label="Nebius API Key", type="password")
343
  analyze_btn = gr.Button("Analyze Image")
344
  analysis_result = gr.Textbox(label="Analysis Result", lines=5)
345
 
346
  with gr.Column():
347
  gr.Markdown("#### 💻 Code Generation Tool")
348
  desc_input = gr.Textbox(label="Description", lines=3)
349
+ nebius_key_tool2 = gr.Textbox(label="Nebius API Key", type="password")
350
  code_btn = gr.Button("Generate Code")
351
  code_result = gr.Code(label="Generated Code", language="html")
352
 
353
  # 事件绑定
354
  generate_btn.click(
355
  fn=screenshot_to_code,
356
+ inputs=[image_input, nebius_key],
357
  outputs=[description_output, html_output]
358
  )
359
 
 
365
 
366
  analyze_btn.click(
367
  fn=analyze_image,
368
+ inputs=[img_tool, nebius_key_tool],
369
  outputs=[analysis_result]
370
  )
371
 
372
  code_btn.click(
373
  fn=generate_html_code,
374
+ inputs=[desc_input, nebius_key_tool2],
375
  outputs=[code_result]
376
  )
377
 
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
  gradio>=4.19.0
2
  pillow>=9.0.0
3
  httpx>=0.24.0
4
- google-generativeai>=0.3.0
5
  lzstring>=1.0.4
6
- requests>=2.28.0
 
 
1
  gradio>=4.19.0
2
  pillow>=9.0.0
3
  httpx>=0.24.0
 
4
  lzstring>=1.0.4
5
+ requests>=2.28.0
6
+ openai>=1.0.0