mgbam commited on
Commit
682ffcf
·
verified ·
1 Parent(s): 53e6ab1

Rename core.py to utils.py

Browse files
Files changed (2) hide show
  1. core.py +0 -49
  2. utils.py +123 -0
core.py DELETED
@@ -1,49 +0,0 @@
1
- # /core.py
2
- """ Core business logic for the code generation application. """
3
- from typing import Dict, List, Optional, Tuple, Generator, Any
4
- from config import (HTML_SYSTEM_PROMPT, GENERIC_SYSTEM_PROMPT, HTML_SYSTEM_PROMPT_WITH_SEARCH,
5
- GENERIC_SYSTEM_PROMPT_WITH_SEARCH, FollowUpSystemPrompt)
6
- from services import llm_service, search_service
7
- from extractor import extract_text_from_file, extract_website_content
8
- from utils import (history_to_messages, remove_code_block, process_image_for_model,
9
- apply_search_replace_changes)
10
-
11
- History = List[Tuple[Optional[str], Optional[str]]]
12
-
13
- def _determine_system_prompt(language: str, enable_search: bool, history: History) -> Tuple[str, bool]:
14
- is_follow_up = bool(history and history[-1][1] and ("<html" in history[-1][1]))
15
- if is_follow_up: return FollowUpSystemPrompt, True
16
-
17
- if language == "html":
18
- return (HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else HTML_SYSTEM_PROMPT), False
19
- else:
20
- base = GENERIC_SYSTEM_PROMPT_WITH_SEARCH if enable_search else GENERIC_SYSTEM_PROMPT
21
- return base.format(language=language), False
22
-
23
- def _prepare_user_content(query: str, image_data: Optional[Any], file_path: Optional[str], website_url: Optional[str], enable_search: bool) -> Any:
24
- context_parts = [query]
25
- if file_path: context_parts.append(f"\n\n--- Reference File ---\n{extract_text_from_file(file_path)[:8000]}")
26
- if website_url: context_parts.append(f"\n\n--- Website to Redesign ---\n{extract_website_content(website_url)}")
27
- full_query = "".join(context_parts)
28
- if enable_search and search_service.is_available(): full_query += f"\n\n--- Web Search Results ---\n{search_service.search(full_query)}"
29
-
30
- if image_data is not None:
31
- return [{"type": "text", "text": full_query}, {"type": "image_url", "image_url": {"url": process_image_for_model(image_data)}}]
32
- return full_query
33
-
34
- def generate_code(query: str, image_data: Optional[Any], file_path: Optional[str], website_url: Optional[str], history: History,
35
- model_config: Dict[str, str], enable_search: bool, language: str) -> Generator[Dict[str, Any], None, None]:
36
- system_prompt, is_follow_up = _determine_system_prompt(language, enable_search, history)
37
- messages = history_to_messages(history, system_prompt)
38
- user_content = _prepare_user_content(query, image_data, file_path, website_url, enable_search)
39
- messages.append({'role': 'user', 'content': user_content})
40
-
41
- content_stream = ""
42
- for chunk in llm_service.generate_code_stream(model_config['id'], messages):
43
- content_stream += chunk
44
- processed_code = apply_search_replace_changes(history[-1][1], content_stream) if is_follow_up else remove_code_block(content_stream)
45
- yield {"code_output": processed_code}
46
-
47
- final_code = apply_search_replace_changes(history[-1][1], content_stream) if is_follow_up else remove_code_block(content_stream)
48
- history.append((query, final_code))
49
- yield {"code_output": final_code, "history": history}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
utils.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Tuple, Dict
2
+ import re
3
+
4
+ # History/message helpers
5
+ History = List[Tuple[str, str]]
6
+ Messages = List[Dict[str, str]]
7
+
8
+ def history_to_messages(history: History, system: str) -> Messages:
9
+ messages = [{'role': 'system', 'content': system}]
10
+ for h in history:
11
+ user_content = h[0]
12
+ if isinstance(user_content, list):
13
+ text_content = ""
14
+ for item in user_content:
15
+ if isinstance(item, dict) and item.get("type") == "text":
16
+ text_content += item.get("text", "")
17
+ user_content = text_content if text_content else str(user_content)
18
+
19
+ messages.append({'role': 'user', 'content': user_content})
20
+ messages.append({'role': 'assistant', 'content': h[1]})
21
+ return messages
22
+
23
+ def messages_to_history(messages: Messages) -> Tuple[str, History]:
24
+ assert messages[0]['role'] == 'system'
25
+ history = []
26
+ for q, r in zip(messages[1::2], messages[2::2]):
27
+ user_content = q['content']
28
+ if isinstance(user_content, list):
29
+ text_content = ""
30
+ for item in user_content:
31
+ if isinstance(item, dict) and item.get("type") == "text":
32
+ text_content += item.get("text", "")
33
+ user_content = text_content if text_content else str(user_content)
34
+
35
+ history.append([user_content, r['content']])
36
+ return history
37
+
38
+ def history_render(history: History):
39
+ return gr.update(visible=True), history
40
+
41
+ def clear_history():
42
+ return [], [], None, ""
43
+
44
+ def update_image_input_visibility(model):
45
+ is_ernie_vl = model.get("id") == "baidu/ERNIE-4.5-VL-424B-A47B-Base-PT"
46
+ is_glm_vl = model.get("id") == "THUDM/GLM-4.1V-9B-Thinking"
47
+ return gr.update(visible=is_ernie_vl or is_glm_vl)
48
+
49
+ def process_image_for_model(image):
50
+ import io, base64
51
+ import numpy as np
52
+ from PIL import Image
53
+
54
+ if image is None:
55
+ return None
56
+
57
+ if isinstance(image, np.ndarray):
58
+ image = Image.fromarray(image)
59
+
60
+ buffer = io.BytesIO()
61
+ image.save(buffer, format='PNG')
62
+ img_str = base64.b64encode(buffer.getvalue()).decode()
63
+ return f"data:image/png;base64,{img_str}"
64
+
65
+ def create_multimodal_message(text, image=None):
66
+ if image is None:
67
+ return {"role": "user", "content": text}
68
+
69
+ content = [
70
+ {"type": "text", "text": text},
71
+ {"type": "image_url", "image_url": {"url": process_image_for_model(image)}}
72
+ ]
73
+ return {"role": "user", "content": content}
74
+
75
+ # Code–block parsing
76
+ def remove_code_block(text):
77
+ patterns = [
78
+ r'```(?:html|HTML)\n([\s\S]+?)\n```',
79
+ r'```\n([\s\S]+?)\n```',
80
+ r'```([\s\S]+?)```'
81
+ ]
82
+ for pattern in patterns:
83
+ match = re.search(pattern, text, re.DOTALL)
84
+ if match:
85
+ extracted = match.group(1).strip()
86
+ if extracted.split('\n', 1)[0].strip().lower() in ['python','html','css','javascript','json','c','cpp','markdown','latex','jinja2','typescript','yaml','dockerfile','shell','r','sql','sql-mssql','sql-mysql','sql-mariadb','sql-sqlite','sql-cassandra','sql-plsql','sql-hive','sql-pgsql','sql-gql','sql-gpsql','sql-sparksql','sql-esper']:
87
+ return extracted.split('\n',1)[1] if '\n' in extracted else ''
88
+ return extracted
89
+ if text.strip().startswith('<!DOCTYPE') or text.strip().startswith('<html'):
90
+ return text.strip()
91
+ if text.strip().startswith('```python'):
92
+ return text.strip()[9:-3].strip()
93
+ lines = text.strip().split('\n',1)
94
+ if lines[0].strip().lower() in ['python','html','css','javascript','json','c','cpp','markdown','latex','jinja2','typescript','yaml','dockerfile','shell','r','sql','sql-mssql','sql-mysql','sql-mariadb','sql-sqlite','sql-cassandra','sql-plsql','sql-hive','sql-pgsql','sql-gql','sql-gpsql','sql-sparksql','sql-esper']:
95
+ return lines[1] if len(lines)>1 else ''
96
+ return text.strip()
97
+
98
+ def parse_transformers_js_output(text):
99
+ files={'index.html':'','index.js':'','style.css':''}
100
+ html_match=re.search(r'```html\s*\n([\s\S]+?)\n```',text,re.IGNORECASE)
101
+ if html_match: files['index.html']=html_match.group(1).strip()
102
+ js_match=re.search(r'```javascript\s*\n([\s\S]+?)\n```',text,re.IGNORECASE)
103
+ if js_match: files['index.js']=js_match.group(1).strip()
104
+ css_match=re.search(r'```css\s*\n([\s\S]+?)\n```',text,re.IGNORECASE)
105
+ if css_match: files['style.css']=css_match.group(1).strip()
106
+ if not(files['index.html'] and files['index.js'] and files['style.css']):
107
+ html_fallback=re.search(r'===\s*index\.html\s*===\n([\s\S]+?)(?=\n===|$)',text,re.IGNORECASE)
108
+ js_fallback=re.search(r'===\s*index\.js\s*===\n([\s\S]+?)(?=\n===|$)',text,re.IGNORECASE)
109
+ css_fallback=re.search(r'===\s*style\.css\s*===\n([\s\S]+?)(?=\n===|$)',text,re.IGNORECASE)
110
+ if html_fallback: files['index.html']=html_fallback.group(1).strip()
111
+ if js_fallback: files['index.js']=js_fallback.group(1).strip()
112
+ if css_fallback: files['style.css']=css_fallback.group(1).strip()
113
+ return files
114
+
115
+ def format_transformers_js_output(files):
116
+ output=[]
117
+ output.append("=== index.html ===")
118
+ output.append(files['index.html'])
119
+ output.append("\n=== index.js ===")
120
+ output.append(files['index.js'])
121
+ output.append("\n=== style.css ===")
122
+ output.append(files['style.css'])
123
+ return '\n'.join(output)