Update app.py
Browse files
app.py
CHANGED
|
@@ -7,139 +7,154 @@ import io
|
|
| 7 |
import subprocess
|
| 8 |
import importlib.util
|
| 9 |
import re
|
| 10 |
-
|
|
|
|
| 11 |
|
| 12 |
# Use OpenRouter API (OpenAI-compatible)
|
| 13 |
-
|
|
|
|
| 14 |
client = openai.OpenAI(
|
| 15 |
-
|
| 16 |
-
|
| 17 |
)
|
| 18 |
|
| 19 |
-
|
| 20 |
|
| 21 |
-
def
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
# Regex patterns for detecting imports
|
| 26 |
-
import_patterns = [
|
| 27 |
-
r'import\s+(\w+)(?:\.\w+)*',
|
| 28 |
-
r'from\s+(\w+)(?:\.\w+)*\s+import',
|
| 29 |
-
]
|
| 30 |
-
|
| 31 |
-
# Regex patterns for detecting package installation commands (pip install)
|
| 32 |
-
pip_patterns = [
|
| 33 |
-
r'pip\s+install\s+([^\s]+)',
|
| 34 |
-
r'install\s+([^\s]+)'
|
| 35 |
-
]
|
| 36 |
-
|
| 37 |
-
# Check for package installations in the code itself
|
| 38 |
-
for pattern in pip_patterns:
|
| 39 |
-
matches = re.findall(pattern, code, re.IGNORECASE)
|
| 40 |
-
for match in matches:
|
| 41 |
-
if match and not match.startswith('"'): # Simple filtering
|
| 42 |
-
required_packages.add(match.split('==')[0].split('>')[0].split('<')[0])
|
| 43 |
-
|
| 44 |
-
# Check for standard imports that might require packages
|
| 45 |
-
lines = code.split('\n')
|
| 46 |
-
for line in lines:
|
| 47 |
-
line = line.strip()
|
| 48 |
-
if line.startswith(('import ', 'from ')):
|
| 49 |
-
# Extract module name after import/from
|
| 50 |
-
for pattern in import_patterns:
|
| 51 |
-
matches = re.findall(pattern, line)
|
| 52 |
-
for module in matches:
|
| 53 |
-
if module and module != '__future__':
|
| 54 |
-
# Map common module names to package names
|
| 55 |
-
module_map = {
|
| 56 |
-
'cv2': 'opencv-python',
|
| 57 |
-
'sklearn': 'scikit-learn',
|
| 58 |
-
'tf': 'tensorflow',
|
| 59 |
-
'torch': 'torch',
|
| 60 |
-
'numpy': 'numpy',
|
| 61 |
-
'pandas': 'pandas',
|
| 62 |
-
'pillow': 'Pillow',
|
| 63 |
-
'matplotlib': 'matplotlib',
|
| 64 |
-
'seaborn': 'seaborn',
|
| 65 |
-
'onnxruntime': 'onnxruntime',
|
| 66 |
-
'rembg': 'rembg',
|
| 67 |
-
'requests': 'requests'
|
| 68 |
-
}
|
| 69 |
-
# Add to required packages (or map to corresponding package)
|
| 70 |
-
if module in module_map:
|
| 71 |
-
required_packages.add(module_map[module])
|
| 72 |
-
else:
|
| 73 |
-
# Use module name as package name (some cases work this way)
|
| 74 |
-
required_packages.add(module)
|
| 75 |
-
|
| 76 |
-
# Remove empty strings and standard library modules
|
| 77 |
-
std_libs = {
|
| 78 |
-
'os', 'sys', 'io', 'json', 're', 'time', 'math', 'random', 'collections',
|
| 79 |
-
'itertools', 'functools', 'operator', 'string', 'pathlib', 'tempfile',
|
| 80 |
-
'subprocess', 'logging', 'argparse', 'csv', 'xml', 'html', 'base64',
|
| 81 |
-
'hashlib', 'urllib', 'http', 'threading', 'multiprocessing', 'socket',
|
| 82 |
-
'asyncio', 'concurrent', 'abc', 'enum', 'dataclasses', 'typing'
|
| 83 |
-
}
|
| 84 |
-
|
| 85 |
-
required_packages = required_packages - std_libs
|
| 86 |
-
|
| 87 |
-
return list(required_packages)
|
| 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 |
You are a Python expert. The user has provided the instruction: "{instruction}"
|
| 127 |
-
And input files: {
|
| 128 |
|
| 129 |
Write a complete, self-contained Python script that:
|
|
|
|
| 130 |
1. Reads the input file(s) from the given paths.
|
| 131 |
2. Performs the requested operation.
|
| 132 |
3. Saves the output file(s) to a temporary directory (use tempfile.mkdtemp() for a temp dir).
|
| 133 |
-
4. At the very end of the script, print exactly one line:
|
| 134 |
(Replace with the actual full path to the generated output file.)
|
| 135 |
|
| 136 |
Use only safe, standard libraries or pre-installed ones. If you need additional packages outside standard libraries,
|
| 137 |
comment them clearly at the top for proper installation.
|
| 138 |
|
| 139 |
Avoid network calls and file deletion outside temporary directories. Handle errors gracefully.
|
| 140 |
-
Do not define main functions or use
|
| 141 |
Keep code structure clean.
|
| 142 |
-
Start Code With import. and do not use try: in start.
|
| 143 |
DO NOT USE MULTILINE STRING OR TRIPLE QUOTES INSIDE CODE.
|
| 144 |
Do not include any markdown formatting or explanations.
|
| 145 |
|
|
@@ -148,276 +163,307 @@ import os
|
|
| 148 |
import tempfile
|
| 149 |
import zipfile
|
| 150 |
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
|
| 155 |
try:
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
except Exception as e:
|
| 160 |
-
|
| 161 |
-
|
| 162 |
|
| 163 |
-
print(f"
|
| 164 |
|
| 165 |
Generate ONLY the Python code.
|
| 166 |
"""
|
| 167 |
-
|
| 168 |
-
try:
|
| 169 |
-
response = client.chat.completions.create(
|
| 170 |
-
model=MODEL_NAME,
|
| 171 |
-
messages=[
|
| 172 |
-
{"role": "system", "content": "You are a helpful Python code generator. Respond only with clean, executable Python code."},
|
| 173 |
-
{"role": "user", "content": prompt}
|
| 174 |
-
],
|
| 175 |
-
max_tokens=1200,
|
| 176 |
-
temperature=0.2,
|
| 177 |
-
stop=["```"]
|
| 178 |
-
)
|
| 179 |
-
|
| 180 |
-
generated_code = response.choices[0].message.content.strip()
|
| 181 |
-
|
| 182 |
-
# Clean up markdown code blocks
|
| 183 |
-
if generated_code.startswith("```python"):
|
| 184 |
-
generated_code = generated_code[10:].strip()
|
| 185 |
-
if generated_code.endswith("```"):
|
| 186 |
-
generated_code = generated_code[:-3].strip()
|
| 187 |
-
|
| 188 |
-
return generated_code
|
| 189 |
-
|
| 190 |
-
except Exception as api_error:
|
| 191 |
-
raise api_error
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
def process_request(instruction, files):
|
| 206 |
-
if not files:
|
| 207 |
-
return "لطفاً حداقل یک فایل آپلود کنید.", None
|
| 208 |
|
| 209 |
-
|
| 210 |
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
generated_code =
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
# Install required packages
|
| 227 |
-
if required_packages:
|
| 228 |
-
try:
|
| 229 |
-
install_packages_if_needed(required_packages)
|
| 230 |
-
except Exception as install_err:
|
| 231 |
-
print(f"Warning: Package installation issues: {install_err}")
|
| 232 |
-
|
| 233 |
-
# Create a safe execution environment
|
| 234 |
-
safe_globals = {
|
| 235 |
-
'__builtins__': {
|
| 236 |
-
'print': print,
|
| 237 |
-
'open': open,
|
| 238 |
-
'range': range,
|
| 239 |
-
'len': len,
|
| 240 |
-
'str': str,
|
| 241 |
-
'int': int,
|
| 242 |
-
'float': float,
|
| 243 |
-
'list': list,
|
| 244 |
-
'dict': dict,
|
| 245 |
-
'tuple': tuple,
|
| 246 |
-
'set': set,
|
| 247 |
-
'bool': bool,
|
| 248 |
-
'type': type,
|
| 249 |
-
'isinstance': isinstance,
|
| 250 |
-
'hasattr': hasattr,
|
| 251 |
-
'getattr': getattr,
|
| 252 |
-
'setattr': setattr,
|
| 253 |
-
'delattr': delattr,
|
| 254 |
-
'abs': abs,
|
| 255 |
-
'all': all,
|
| 256 |
-
'any': any,
|
| 257 |
-
'bin': bin,
|
| 258 |
-
'chr': chr,
|
| 259 |
-
'complex': complex,
|
| 260 |
-
'divmod': divmod,
|
| 261 |
-
'enumerate': enumerate,
|
| 262 |
-
'format': format,
|
| 263 |
-
'hash': hash,
|
| 264 |
-
'hex': hex,
|
| 265 |
-
'id': id,
|
| 266 |
-
'iter': iter,
|
| 267 |
-
'max': max,
|
| 268 |
-
'min': min,
|
| 269 |
-
'next': next,
|
| 270 |
-
'oct': oct,
|
| 271 |
-
'ord': ord,
|
| 272 |
-
'pow': pow,
|
| 273 |
-
'repr': repr,
|
| 274 |
-
'round': round,
|
| 275 |
-
'slice': slice,
|
| 276 |
-
'sorted': sorted,
|
| 277 |
-
'sum': sum,
|
| 278 |
-
'zip': zip,
|
| 279 |
-
'__import__': __import__,
|
| 280 |
-
'__name__': '__main__', # Fix for __name__ error
|
| 281 |
-
'exit': sys.exit,
|
| 282 |
-
'True': True,
|
| 283 |
-
'False': False,
|
| 284 |
-
'None': None,
|
| 285 |
-
},
|
| 286 |
-
'__name__': '__main__', # Explicitly set __name__
|
| 287 |
-
'os': os,
|
| 288 |
-
'tempfile': tempfile,
|
| 289 |
-
'sys': sys,
|
| 290 |
-
'subprocess': subprocess,
|
| 291 |
-
'importlib': importlib,
|
| 292 |
-
're': re,
|
| 293 |
-
'json': __import__('json'),
|
| 294 |
-
'time': __import__('time'),
|
| 295 |
-
'math': __import__('math'),
|
| 296 |
-
'random': __import__('random'),
|
| 297 |
-
'collections': __import__('collections'),
|
| 298 |
-
'itertools': __import__('itertools'),
|
| 299 |
-
'functools': __import__('functools'),
|
| 300 |
-
'operator': __import__('operator'),
|
| 301 |
-
'pathlib': __import__('pathlib'),
|
| 302 |
-
'logging': __import__('logging'),
|
| 303 |
-
'argparse': __import__('argparse'),
|
| 304 |
-
'csv': __import__('csv'),
|
| 305 |
-
'base64': __import__('base64'),
|
| 306 |
-
'hashlib': __import__('hashlib'),
|
| 307 |
-
'urllib': __import__('urllib'),
|
| 308 |
-
'http': __import__('http'),
|
| 309 |
-
'socket': __import__('socket'),
|
| 310 |
-
'threading': __import__('threading'),
|
| 311 |
-
'multiprocessing': __import__('multiprocessing'),
|
| 312 |
-
'asyncio': __import__('asyncio'),
|
| 313 |
-
'concurrent': __import__('concurrent'),
|
| 314 |
-
'abc': __import__('abc'),
|
| 315 |
-
'enum': __import__('enum'),
|
| 316 |
-
'dataclasses': __import__('dataclasses'),
|
| 317 |
-
'typing': __import__('typing'),
|
| 318 |
-
'PIL': __import__('PIL', fromlist=['Image']),
|
| 319 |
-
'zipfile': __import__('zipfile'),
|
| 320 |
-
'requests': __import__('requests') if 'requests' in required_packages else None,
|
| 321 |
-
}
|
| 322 |
-
|
| 323 |
-
# Clean up globals to remove None entries (prevents AttributeError)
|
| 324 |
-
safe_globals_clean = {k: v for k, v in safe_globals.items() if v is not None}
|
| 325 |
-
|
| 326 |
-
# Wrap original code in try/except for clean execution
|
| 327 |
-
wrapped_code = f"""
|
| 328 |
try:
|
| 329 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 330 |
except Exception as e:
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
try:
|
| 343 |
-
|
| 344 |
-
except
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
|
|
|
|
|
|
| 374 |
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
return result_text, output_path
|
| 379 |
-
else:
|
| 380 |
-
return f"فایل خروجی یافت نشد. خروجی:\n{stdout_output}\nکد:\n{wrapped_code}", None
|
| 381 |
-
|
| 382 |
-
except Exception as gen_error:
|
| 383 |
-
return f"خطا در تولید کد (OpenRouter): {str(gen_error)}\nپرامپت:\n{instruction}", None
|
| 384 |
|
| 385 |
# Gradio Interface
|
|
|
|
| 386 |
with gr.Blocks(title="AI File Processor - Final Robust Version") as demo:
|
| 387 |
-
|
|
|
|
| 388 |
# پردازشگر فایل با هوش مصنوعی (نسخه تمامخطا)
|
|
|
|
| 389 |
## اجرای قابل اعتماد بدون مشکل از `__name__` تا ساختار
|
| 390 |
|
| 391 |
**ورژن نهایی با تمام رفعهای خطا:**
|
| 392 |
-
✅ رفع تمام تعاریف `__name__`
|
| 393 |
-
✅ رفع مشکلات ساختاری `try/except`
|
| 394 |
-
✅ اجرای امن و خطاگذار
|
| 395 |
-
✅ افزودن نیمساختار `try/except` مناسب
|
| 396 |
-
✅ اعتبارسنجی دقیق پیش از اجرای کد
|
| 397 |
|
| 398 |
**قابلیتها:**
|
| 399 |
-
✅ پشتیبانی از تمام عملیات پیچیده
|
| 400 |
-
✅ تشخیص خودکار پکیجهای بیشتر
|
| 401 |
-
✅ نصب خودکار تمام ماژولهای مورد نیاز
|
| 402 |
-
✅ گزارشهای دقیق خطا
|
| 403 |
|
| 404 |
**نوت:** این ورژن 99% از ارورها را حل کرده و با تمام کدهای تولید شده تست شده است.
|
| 405 |
""")
|
| 406 |
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
|
|
|
|
|
|
| 421 |
|
| 422 |
-
if
|
| 423 |
-
|
|
|
|
| 7 |
import subprocess
|
| 8 |
import importlib.util
|
| 9 |
import re
|
| 10 |
+
import textwrap
|
| 11 |
+
from contextlib import redirect\_stdout
|
| 12 |
|
| 13 |
# Use OpenRouter API (OpenAI-compatible)
|
| 14 |
+
|
| 15 |
+
OPENROUTER\_API\_KEY = os.getenv("OPENROUTER\_API\_KEY")
|
| 16 |
client = openai.OpenAI(
|
| 17 |
+
api\_key=OPENROUTER\_API\_KEY,
|
| 18 |
+
base\_url="[https://openrouter.ai/api/v1](https://openrouter.ai/api/v1)"
|
| 19 |
)
|
| 20 |
|
| 21 |
+
MODEL\_NAME = "openai/gpt-oss-20b\:free"
|
| 22 |
|
| 23 |
+
def detect\_required\_packages(code):
|
| 24 |
+
"""Detect required packages from Python code."""
|
| 25 |
+
required\_packages = set()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
+
```
|
| 28 |
+
# Regex patterns for detecting imports
|
| 29 |
+
import_patterns = [
|
| 30 |
+
r'import\s+(\w+)(?:\.\w+)*',
|
| 31 |
+
r'from\s+(\w+)(?:\.\w+)*\s+import',
|
| 32 |
+
]
|
| 33 |
+
|
| 34 |
+
# Regex patterns for detecting package installation commands (pip install)
|
| 35 |
+
pip_patterns = [
|
| 36 |
+
r'pip\s+install\s+([^\s]+)',
|
| 37 |
+
r'install\s+([^\s]+)'
|
| 38 |
+
]
|
| 39 |
+
|
| 40 |
+
# Check for package installations in the code itself
|
| 41 |
+
for pattern in pip_patterns:
|
| 42 |
+
matches = re.findall(pattern, code, re.IGNORECASE)
|
| 43 |
+
for match in matches:
|
| 44 |
+
if match and not match.startswith('"'): # Simple filtering
|
| 45 |
+
required_packages.add(match.split('==')[0].split('>')[0].split('<')[0])
|
| 46 |
+
|
| 47 |
+
# Check for standard imports that might require packages
|
| 48 |
+
lines = code.split('\n')
|
| 49 |
+
for line in lines:
|
| 50 |
+
line = line.strip()
|
| 51 |
+
if line.startswith(('import ', 'from ')):
|
| 52 |
+
# Extract module name after import/from
|
| 53 |
+
for pattern in import_patterns:
|
| 54 |
+
matches = re.findall(pattern, line)
|
| 55 |
+
for module in matches:
|
| 56 |
+
if module and module != '__future__':
|
| 57 |
+
# Map common module names to package names
|
| 58 |
+
module_map = {
|
| 59 |
+
'cv2': 'opencv-python',
|
| 60 |
+
'sklearn': 'scikit-learn',
|
| 61 |
+
'tf': 'tensorflow',
|
| 62 |
+
'torch': 'torch',
|
| 63 |
+
'numpy': 'numpy',
|
| 64 |
+
'pandas': 'pandas',
|
| 65 |
+
'pillow': 'Pillow',
|
| 66 |
+
'matplotlib': 'matplotlib',
|
| 67 |
+
'seaborn': 'seaborn',
|
| 68 |
+
'onnxruntime': 'onnxruntime',
|
| 69 |
+
'rembg': 'rembg',
|
| 70 |
+
'requests': 'requests'
|
| 71 |
+
}
|
| 72 |
+
# Add to required packages (or map to corresponding package)
|
| 73 |
+
if module in module_map:
|
| 74 |
+
required_packages.add(module_map[module])
|
| 75 |
+
else:
|
| 76 |
+
# Use module name as package name (some cases work this way)
|
| 77 |
+
required_packages.add(module)
|
| 78 |
+
|
| 79 |
+
# Remove empty strings and standard library modules
|
| 80 |
+
std_libs = {
|
| 81 |
+
'os', 'sys', 'io', 'json', 're', 'time', 'math', 'random', 'collections',
|
| 82 |
+
'itertools', 'functools', 'operator', 'string', 'pathlib', 'tempfile',
|
| 83 |
+
'subprocess', 'logging', 'argparse', 'csv', 'xml', 'html', 'base64',
|
| 84 |
+
'hashlib', 'urllib', 'http', 'threading', 'multiprocessing', 'socket',
|
| 85 |
+
'asyncio', 'concurrent', 'abc', 'enum', 'dataclasses', 'typing'
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
required_packages = required_packages - std_libs
|
| 89 |
+
|
| 90 |
+
return list(required_packages)
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
def install\_package(package\_name):
|
| 94 |
+
"""Install a package using pip if it's not already installed."""
|
| 95 |
+
try:
|
| 96 |
+
\# Try to detect by module name for some common packages
|
| 97 |
+
module\_name = package\_name
|
| 98 |
+
\# handle some known cases where package name != import name
|
| 99 |
+
pkg\_to\_module = {
|
| 100 |
+
'opencv-python': 'cv2',
|
| 101 |
+
'Pillow': 'PIL',
|
| 102 |
+
'scikit-learn': 'sklearn'
|
| 103 |
+
}
|
| 104 |
+
module\_name = pkg\_to\_module.get(package\_name, package\_name)
|
| 105 |
+
spec = importlib.util.find\_spec(module\_name)
|
| 106 |
+
if spec is None:
|
| 107 |
+
print(f"Installing package: {package\_name}")
|
| 108 |
+
subprocess.check\_call(\[
|
| 109 |
+
sys.executable, "-m", "pip", "install", "--quiet", package\_name
|
| 110 |
+
])
|
| 111 |
+
print(f"✅ {package\_name} installed successfully.")
|
| 112 |
+
else:
|
| 113 |
+
print(f"✅ {package\_name} already installed.")
|
| 114 |
+
except Exception as e:
|
| 115 |
+
print(f"❌ Failed to install {package\_name}: {str(e)}")
|
| 116 |
+
raise RuntimeError(f"Installation failed for {package\_name}: {str(e)}")
|
| 117 |
+
|
| 118 |
+
def install\_packages\_if\_needed(packages):
|
| 119 |
+
"""Install all required packages."""
|
| 120 |
+
if not packages:
|
| 121 |
+
print("No packages to install.")
|
| 122 |
+
return True
|
| 123 |
+
|
| 124 |
+
```
|
| 125 |
+
for package in packages:
|
| 126 |
+
if package:
|
| 127 |
+
try:
|
| 128 |
+
install_package(package)
|
| 129 |
+
except Exception as e:
|
| 130 |
+
print(f"⚠️ Could not install {package}: {e}")
|
| 131 |
+
# Continue with other packages even if one fails
|
| 132 |
|
| 133 |
+
return True
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
def generate\_code\_with\_openrouter(instruction, file\_paths):
|
| 137 |
+
"""
|
| 138 |
+
Generate Python code using OpenRouter API.
|
| 139 |
+
"""
|
| 140 |
+
prompt = f"""
|
| 141 |
You are a Python expert. The user has provided the instruction: "{instruction}"
|
| 142 |
+
And input files: {file\_paths} (these paths are available in the current working directory).
|
| 143 |
|
| 144 |
Write a complete, self-contained Python script that:
|
| 145 |
+
|
| 146 |
1. Reads the input file(s) from the given paths.
|
| 147 |
2. Performs the requested operation.
|
| 148 |
3. Saves the output file(s) to a temporary directory (use tempfile.mkdtemp() for a temp dir).
|
| 149 |
+
4. At the very end of the script, print exactly one line: OUTPUT\_FILE\_PATH: /full/path/to/output/file.ext
|
| 150 |
(Replace with the actual full path to the generated output file.)
|
| 151 |
|
| 152 |
Use only safe, standard libraries or pre-installed ones. If you need additional packages outside standard libraries,
|
| 153 |
comment them clearly at the top for proper installation.
|
| 154 |
|
| 155 |
Avoid network calls and file deletion outside temporary directories. Handle errors gracefully.
|
| 156 |
+
Do not define main functions or use **name** == "**main**".
|
| 157 |
Keep code structure clean.
|
|
|
|
| 158 |
DO NOT USE MULTILINE STRING OR TRIPLE QUOTES INSIDE CODE.
|
| 159 |
Do not include any markdown formatting or explanations.
|
| 160 |
|
|
|
|
| 163 |
import tempfile
|
| 164 |
import zipfile
|
| 165 |
|
| 166 |
+
input\_path = '{file\_paths\[0]}'
|
| 167 |
+
temp\_dir = tempfile.mkdtemp()
|
| 168 |
+
output\_zip\_path = os.path.join(temp\_dir, 'output.zip')
|
| 169 |
|
| 170 |
try:
|
| 171 |
+
with zipfile.ZipFile(output\_zip\_path, 'w', compression=zipfile.ZIP\_DEFLATED) as zipf:
|
| 172 |
+
arcname = os.path.basename(input\_path)
|
| 173 |
+
zipf.write(input\_path, arcname=arcname)
|
| 174 |
except Exception as e:
|
| 175 |
+
print(f"Error creating zip: {{e}}")
|
| 176 |
+
exit(1)
|
| 177 |
|
| 178 |
+
print(f"OUTPUT\_FILE\_PATH: {{output\_zip\_path}}")
|
| 179 |
|
| 180 |
Generate ONLY the Python code.
|
| 181 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
|
| 183 |
+
````
|
| 184 |
+
try:
|
| 185 |
+
response = client.chat.completions.create(
|
| 186 |
+
model=MODEL_NAME,
|
| 187 |
+
messages=[
|
| 188 |
+
{"role": "system", "content": "You are a helpful Python code generator. Respond only with clean, executable Python code."},
|
| 189 |
+
{"role": "user", "content": prompt}
|
| 190 |
+
],
|
| 191 |
+
max_tokens=1200,
|
| 192 |
+
temperature=0.2,
|
| 193 |
+
stop=["```"]
|
| 194 |
+
)
|
|
|
|
|
|
|
|
|
|
| 195 |
|
| 196 |
+
generated_code = response.choices[0].message.content.strip()
|
| 197 |
|
| 198 |
+
# Clean up markdown code blocks
|
| 199 |
+
if generated_code.startswith("```python"):
|
| 200 |
+
generated_code = generated_code[10:].strip()
|
| 201 |
+
if generated_code.endswith("```"):
|
| 202 |
+
generated_code = generated_code[:-3].strip()
|
| 203 |
+
|
| 204 |
+
return generated_code
|
| 205 |
+
|
| 206 |
+
except Exception as api_error:
|
| 207 |
+
raise api_error
|
| 208 |
+
````
|
| 209 |
+
|
| 210 |
+
def safe\_exec\_code(code, globals\_dict, locals\_dict):
|
| 211 |
+
"""Safely execute code and return output."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
try:
|
| 213 |
+
\# First try to compile just to catch syntax errors
|
| 214 |
+
compiled\_code = compile(code, '<string>', 'exec')
|
| 215 |
+
|
| 216 |
+
```
|
| 217 |
+
# Run the code
|
| 218 |
+
exec(compiled_code, globals_dict, locals_dict)
|
| 219 |
+
return True, None
|
| 220 |
except Exception as e:
|
| 221 |
+
return False, str(e)
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
def process\_request(instruction, files):
|
| 225 |
+
if not files:
|
| 226 |
+
return "لطفاً حداقل یک فایل آپلود کنید.", None
|
| 227 |
+
|
| 228 |
+
```
|
| 229 |
+
file_paths = [file.name for file in files]
|
| 230 |
+
|
| 231 |
+
try:
|
| 232 |
+
# Generate code using OpenRouter
|
| 233 |
+
generated_code = generate_code_with_openrouter(instruction, file_paths)
|
| 234 |
+
|
| 235 |
+
if not generated_code or len(generated_code) < 50:
|
| 236 |
+
return f"کد مناسبی تولید نشد. پرامپت: {instruction}\nکد تولید شده:\n{generated_code}", None
|
| 237 |
+
|
| 238 |
+
print("--- Generated code ---")
|
| 239 |
+
print(repr(generated_code)) # Debugging
|
| 240 |
+
print("---------------------")
|
| 241 |
+
|
| 242 |
+
# Detect required packages
|
| 243 |
+
required_packages = detect_required_packages(generated_code)
|
| 244 |
+
print("Detected required packages:", required_packages)
|
| 245 |
+
|
| 246 |
+
# Install required packages
|
| 247 |
+
if required_packages:
|
| 248 |
try:
|
| 249 |
+
install_packages_if_needed(required_packages)
|
| 250 |
+
except Exception as install_err:
|
| 251 |
+
print(f"Warning: Package installation issues: {install_err}")
|
| 252 |
+
|
| 253 |
+
# Create a safe execution environment
|
| 254 |
+
# Conditionally import heavy/optional libs only if detected to avoid import errors
|
| 255 |
+
optional_imports = {}
|
| 256 |
+
if 'Pillow' in required_packages or 'PIL' in required_packages:
|
| 257 |
+
try:
|
| 258 |
+
optional_imports['PIL'] = __import__('PIL', fromlist=['Image'])
|
| 259 |
+
except Exception as e:
|
| 260 |
+
optional_imports['PIL'] = None
|
| 261 |
+
print(f"Warning: PIL import failed: {e}")
|
| 262 |
+
if 'requests' in required_packages:
|
| 263 |
+
try:
|
| 264 |
+
optional_imports['requests'] = __import__('requests')
|
| 265 |
+
except Exception as e:
|
| 266 |
+
optional_imports['requests'] = None
|
| 267 |
+
print(f"Warning: requests import failed: {e}")
|
| 268 |
+
|
| 269 |
+
safe_globals = {
|
| 270 |
+
'__builtins__': {
|
| 271 |
+
'print': print,
|
| 272 |
+
'open': open,
|
| 273 |
+
'range': range,
|
| 274 |
+
'len': len,
|
| 275 |
+
'str': str,
|
| 276 |
+
'int': int,
|
| 277 |
+
'float': float,
|
| 278 |
+
'list': list,
|
| 279 |
+
'dict': dict,
|
| 280 |
+
'tuple': tuple,
|
| 281 |
+
'set': set,
|
| 282 |
+
'bool': bool,
|
| 283 |
+
'type': type,
|
| 284 |
+
'isinstance': isinstance,
|
| 285 |
+
'hasattr': hasattr,
|
| 286 |
+
'getattr': getattr,
|
| 287 |
+
'setattr': setattr,
|
| 288 |
+
'delattr': delattr,
|
| 289 |
+
'abs': abs,
|
| 290 |
+
'all': all,
|
| 291 |
+
'any': any,
|
| 292 |
+
'bin': bin,
|
| 293 |
+
'chr': chr,
|
| 294 |
+
'complex': complex,
|
| 295 |
+
'divmod': divmod,
|
| 296 |
+
'enumerate': enumerate,
|
| 297 |
+
'format': format,
|
| 298 |
+
'hash': hash,
|
| 299 |
+
'hex': hex,
|
| 300 |
+
'id': id,
|
| 301 |
+
'iter': iter,
|
| 302 |
+
'max': max,
|
| 303 |
+
'min': min,
|
| 304 |
+
'next': next,
|
| 305 |
+
'oct': oct,
|
| 306 |
+
'ord': ord,
|
| 307 |
+
'pow': pow,
|
| 308 |
+
'repr': repr,
|
| 309 |
+
'round': round,
|
| 310 |
+
'slice': slice,
|
| 311 |
+
'sorted': sorted,
|
| 312 |
+
'sum': sum,
|
| 313 |
+
'zip': zip,
|
| 314 |
+
'__import__': __import__,
|
| 315 |
+
'exit': sys.exit,
|
| 316 |
+
'True': True,
|
| 317 |
+
'False': False,
|
| 318 |
+
'None': None,
|
| 319 |
+
},
|
| 320 |
+
'__name__': '__main__', # Explicitly set __name__
|
| 321 |
+
'os': os,
|
| 322 |
+
'tempfile': tempfile,
|
| 323 |
+
'sys': sys,
|
| 324 |
+
'subprocess': subprocess,
|
| 325 |
+
'importlib': importlib,
|
| 326 |
+
're': re,
|
| 327 |
+
'json': __import__('json'),
|
| 328 |
+
'time': __import__('time'),
|
| 329 |
+
'math': __import__('math'),
|
| 330 |
+
'random': __import__('random'),
|
| 331 |
+
'collections': __import__('collections'),
|
| 332 |
+
'itertools': __import__('itertools'),
|
| 333 |
+
'functools': __import__('functools'),
|
| 334 |
+
'operator': __import__('operator'),
|
| 335 |
+
'pathlib': __import__('pathlib'),
|
| 336 |
+
'logging': __import__('logging'),
|
| 337 |
+
'argparse': __import__('argparse'),
|
| 338 |
+
'csv': __import__('csv'),
|
| 339 |
+
'base64': __import__('base64'),
|
| 340 |
+
'hashlib': __import__('hashlib'),
|
| 341 |
+
'urllib': __import__('urllib'),
|
| 342 |
+
'http': __import__('http'),
|
| 343 |
+
'socket': __import__('socket'),
|
| 344 |
+
'threading': __import__('threading'),
|
| 345 |
+
'multiprocessing': __import__('multiprocessing'),
|
| 346 |
+
'asyncio': __import__('asyncio'),
|
| 347 |
+
'concurrent': __import__('concurrent'),
|
| 348 |
+
'abc': __import__('abc'),
|
| 349 |
+
'enum': __import__('enum'),
|
| 350 |
+
'dataclasses': __import__('dataclasses'),
|
| 351 |
+
'typing': __import__('typing'),
|
| 352 |
+
'zipfile': __import__('zipfile'),
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
# Add optional imports only if available
|
| 356 |
+
for k, v in optional_imports.items():
|
| 357 |
+
if v is not None:
|
| 358 |
+
safe_globals[k] = v
|
| 359 |
+
|
| 360 |
+
# Clean up globals to remove None entries (prevents AttributeError)
|
| 361 |
+
safe_globals_clean = {k: v for k, v in safe_globals.items() if v is not None}
|
| 362 |
+
|
| 363 |
+
# Prepare wrapped code by properly indenting the generated code inside a try/except block
|
| 364 |
+
# This avoids producing an unindented 'try:' that causes SyntaxError.
|
| 365 |
+
normalized_code = generated_code.replace('\r\n', '\n').rstrip()
|
| 366 |
+
indented_code = textwrap.indent(normalized_code, ' ')
|
| 367 |
+
wrapped_code = (
|
| 368 |
+
"try:\n"
|
| 369 |
+
+ indented_code
|
| 370 |
+
+ "\nexcept Exception as e:\n"
|
| 371 |
+
" print(f\"ERROR: {e}\")\n"
|
| 372 |
+
" import traceback\n"
|
| 373 |
+
" traceback.print_exc()\n"
|
| 374 |
+
" sys.exit(1)\n"
|
| 375 |
+
)
|
| 376 |
+
|
| 377 |
+
print("--- Wrapped code ---")
|
| 378 |
+
print(repr(wrapped_code)) # Debugging
|
| 379 |
+
print("---------------------")
|
| 380 |
+
|
| 381 |
+
# Validate that wrapped code compiles properly
|
| 382 |
+
try:
|
| 383 |
+
compile(wrapped_code, '<wrapped_string>', 'exec')
|
| 384 |
+
except SyntaxError as se:
|
| 385 |
+
return f"Syntax error in wrapped code: {se}\nWrapped code:\n{wrapped_code}", None
|
| 386 |
+
|
| 387 |
+
# Capture output
|
| 388 |
+
f = io.StringIO()
|
| 389 |
+
output_path = None
|
| 390 |
+
|
| 391 |
+
with redirect_stdout(f):
|
| 392 |
+
try:
|
| 393 |
+
# Execute code safely
|
| 394 |
+
exec_result, exec_error = safe_exec_code(wrapped_code, safe_globals_clean, {})
|
| 395 |
+
|
| 396 |
+
if not exec_result:
|
| 397 |
+
return f"Execution failed: {exec_error}\nCode:\n{wrapped_code}", None
|
| 398 |
+
|
| 399 |
+
# Get stdout output
|
| 400 |
+
stdout_output = f.getvalue()
|
| 401 |
+
print("STDOUT OUTPUT:")
|
| 402 |
+
print(stdout_output)
|
| 403 |
+
|
| 404 |
+
# Extract output file path
|
| 405 |
+
if "OUTPUT_FILE_PATH:" in stdout_output:
|
| 406 |
+
output_path = stdout_output.split("OUTPUT_FILE_PATH:")[-1].strip()
|
| 407 |
+
output_path = output_path.split('\n')[0].strip()
|
| 408 |
|
| 409 |
+
except Exception as exec_error:
|
| 410 |
+
error_msg = f"Error during execution: {str(exec_error)}"
|
| 411 |
+
import traceback
|
| 412 |
+
error_msg += "\n" + traceback.format_exc()
|
| 413 |
+
return f"{error_msg}\nCode:\n{wrapped_code}", None
|
| 414 |
+
|
| 415 |
+
# Clean up
|
| 416 |
+
if output_path and os.path.exists(output_path):
|
| 417 |
+
result_text = f"عملیات با موفقیت انجام شد!\nکد تولید شده توسط OpenRouter:\n{wrapped_code}\n\nخروجی stdout:\n{stdout_output}"
|
| 418 |
+
return result_text, output_path
|
| 419 |
+
else:
|
| 420 |
+
return f"فایل خروجی یافت نشد. خروجی:\n{stdout_output}\nکد:\n{wrapped_code}", None
|
| 421 |
|
| 422 |
+
except Exception as gen_error:
|
| 423 |
+
return f"خطا در تولید کد (OpenRouter): {str(gen_error)}\nپرامپت:\n{instruction}", None
|
| 424 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 425 |
|
| 426 |
# Gradio Interface
|
| 427 |
+
|
| 428 |
with gr.Blocks(title="AI File Processor - Final Robust Version") as demo:
|
| 429 |
+
gr.Markdown("""
|
| 430 |
+
|
| 431 |
# پردازشگر فایل با هوش مصنوعی (نسخه تمامخطا)
|
| 432 |
+
|
| 433 |
## اجرای قابل اعتماد بدون مشکل از `__name__` تا ساختار
|
| 434 |
|
| 435 |
**ورژن نهایی با تمام رفعهای خطا:**
|
| 436 |
+
✅ رفع تمام تعاریف `__name__`
|
| 437 |
+
✅ رفع مشکلات ساختاری `try/except`
|
| 438 |
+
✅ اجرای امن و خطاگذار
|
| 439 |
+
✅ افزودن نیمساختار `try/except` مناسب
|
| 440 |
+
✅ اعتبارسنجی دقیق پیش از اجرای کد
|
| 441 |
|
| 442 |
**قابلیتها:**
|
| 443 |
+
✅ پشتیبانی از تمام عملیات پیچیده
|
| 444 |
+
✅ تشخیص خودکار پکیجهای بیشتر
|
| 445 |
+
✅ نصب خودکار تمام ماژولهای مورد نیاز
|
| 446 |
+
✅ گزارشهای دقیق خطا
|
| 447 |
|
| 448 |
**نوت:** این ورژن 99% از ارورها را حل کرده و با تمام کدهای تولید شده تست شده است.
|
| 449 |
""")
|
| 450 |
|
| 451 |
+
```
|
| 452 |
+
with gr.Row():
|
| 453 |
+
instruction_input = gr.Textbox(label="دستور (مثال: بک گراند عکس را حذف کن)", placeholder="دستور خود را بنویسید...", lines=3)
|
| 454 |
+
files_input = gr.File(file_count="multiple", label="فایل(ها)")
|
| 455 |
+
|
| 456 |
+
process_btn = gr.Button("پردازش با OpenRouter")
|
| 457 |
+
|
| 458 |
+
output_text = gr.Textbox(label="نتیجه و کد", lines=15)
|
| 459 |
+
output_file = gr.File(label="فایل خروجی (لینک دانلود)")
|
| 460 |
+
|
| 461 |
+
process_btn.click(
|
| 462 |
+
fn=process_request,
|
| 463 |
+
inputs=[instruction_input, files_input],
|
| 464 |
+
outputs=[output_text, output_file]
|
| 465 |
+
)
|
| 466 |
+
```
|
| 467 |
|
| 468 |
+
if **name** == "**main**":
|
| 469 |
+
demo.launch(share=True)
|