Paulwalker4884 commited on
Commit
048d6cb
·
1 Parent(s): 889f60f

Initial commit

Browse files
Files changed (1) hide show
  1. app.py +122 -329
app.py CHANGED
@@ -9,39 +9,39 @@ from openai import OpenAI
9
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
10
  logger = logging.getLogger(__name__)
11
 
12
- # تنظیم API Key برای OpenAI
13
  logger.info("Starting application setup")
14
- openai_api_key = os.getenv("OPENAI_API_KEY")
15
- if not openai_api_key:
16
- logger.warning("OPENAI_API_KEY not found in environment variables")
17
- client = None
18
- else:
19
- try:
20
- client = OpenAI(
21
- api_key=openai_api_key,
22
- timeout=30.0
23
- )
24
- logger.info("✅ OpenAI client initialized successfully")
25
-
26
- # تست اتصال
27
- try:
28
- test_response = client.models.list()
29
- logger.info("✅ API connection test successful")
30
- except Exception as e:
31
- logger.warning(f"⚠️ API test failed but client created: {e}")
32
-
33
- except Exception as e:
34
- logger.error(f"❌ Failed to initialize OpenAI client: {e}")
35
- client = None
36
 
37
- # مسیر فایل دیتابیس
38
- DB_PATH = "christopher_history.db"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  # ایجاد دیتابیس
41
  def init_db():
42
  logger.info("🗄️ Initializing database")
43
  try:
44
- with sqlite3.connect(DB_PATH) as conn:
45
  cursor = conn.cursor()
46
  cursor.execute('''CREATE TABLE IF NOT EXISTS code_history (
47
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -56,341 +56,134 @@ def init_db():
56
  logger.info("✅ Database initialized successfully")
57
  except Exception as e:
58
  logger.error(f"❌ Database initialization error: {e}")
 
59
 
60
  # ذخیره در دیتابیس
61
- def save_to_db(user_input, language, generated_code, prompt_used="", success=True):
62
- logger.info("💾 Saving to database")
63
  try:
64
- with sqlite3.connect(DB_PATH) as conn:
65
  cursor = conn.cursor()
66
- cursor.execute("""INSERT INTO code_history
67
- (user_input, language, generated_code, prompt_used, timestamp, success)
68
- VALUES (?, ?, ?, ?, ?, ?)""",
69
- (user_input, language, generated_code, prompt_used,
70
- datetime.now().isoformat(), success))
71
  conn.commit()
72
- logger.info("✅ Successfully saved to database")
73
  except Exception as e:
74
  logger.error(f"❌ Database save error: {e}")
75
 
76
  # دریافت تاریخچه
77
- def get_history(limit=10):
78
- logger.info("📜 Retrieving history from database")
79
  try:
80
- with sqlite3.connect(DB_PATH) as conn:
81
  cursor = conn.cursor()
82
- cursor.execute("""SELECT id, user_input, language, generated_code, timestamp, success
83
- FROM code_history
84
- ORDER BY timestamp DESC
85
- LIMIT ?""", (limit,))
86
  rows = cursor.fetchall()
87
-
88
  if not rows:
89
- return "📝 هیچ تاریخچه‌ای موجود نیست."
90
-
91
- history_text = f"📋 **تاریخچه آخرین {len(rows)} درخواست:**\n\n"
92
-
93
- for i, row in enumerate(rows, 1):
94
- status_icon = "✅" if row[5] else "❌"
95
- history_text += f"**{i}. {status_icon} درخواست #{row[0]}**\n"
96
- history_text += f"📝 **درخواست:** {row[1]}\n"
97
- history_text += f"🔧 **زبان:** {row[2]}\n"
98
- history_text += f" **زمان:** {row[4]}\n"
99
- history_text += f"💻 **کد تولیدشده:**\n```{row[2].lower()}\n{row[3][:200]}{'...' if len(row[3]) > 200 else ''}\n```\n"
100
- history_text += "─" * 50 + "\n\n"
101
-
102
  return history_text
103
-
104
  except Exception as e:
105
  logger.error(f"❌ History retrieval error: {e}")
106
- return f"خطا در دریافت تاریخچه: {str(e)}"
107
 
108
  # تولید کد
109
- def generate_code(text, language):
110
- logger.info(f"🚀 Generating code for: {text[:50]}... in {language}")
111
-
112
- if client is None:
113
- error_msg = "❌ خطا: اتصال به API برقرار نشد. لطفاً API Key را بررسی کنید."
114
- error_code = f"# خطا در اتصال به سرویس\n# درخواست: {text}\nprint('لطفاً API Key را در تنظیمات OpenAI اضافه کنید')"
115
- save_to_db(text, language, error_code, error_msg, success=False)
116
- return error_msg, error_code
117
-
118
  try:
119
- # لیست مدل‌های OpenAI برای تست
120
- models_to_try = [
121
- "gpt-4o",
122
- "gpt-3.5-turbo"
123
- ]
124
-
125
- system_prompt = f"""You are an expert {language} programmer.
126
- Generate clean, well-documented, and executable code with proper comments.
127
- Always include error handling where appropriate."""
128
-
129
- user_prompt = f"""Create a complete {language} program that: {text}
130
-
131
- Requirements:
132
- - Write clean, readable code
133
- - Include helpful comments (both English and Persian if helpful)
134
- - Add proper error handling
135
- - Make sure the code is executable
136
- - Follow {language} best practices
137
-
138
- Please provide only the code, no extra explanations."""
139
-
140
- code_generated = False
141
- response_content = ""
142
- model_used = ""
143
-
144
- # تلاش با مدل‌های مختلف
145
- for model in models_to_try:
146
- try:
147
- logger.info(f"🔄 Trying model: {model}")
148
- response = client.chat.completions.create(
149
- model=model,
150
- messages=[
151
- {"role": "system", "content": system_prompt},
152
- {"role": "user", "content": user_prompt}
153
- ],
154
- max_tokens=1500,
155
- temperature=0.3,
156
- )
157
-
158
- response_content = response.choices[0].message.content.strip()
159
- model_used = model
160
- code_generated = True
161
- logger.info(f"✅ Successfully used model: {model}")
162
- break
163
-
164
- except Exception as model_error:
165
- logger.warning(f"⚠️ Model {model} failed: {model_error}")
166
  continue
167
-
168
- if not code_generated:
169
- error_msg = "❌ همه مدل‌ها شکست خوردند"
170
- error_code = f"# خطا در تولید کد\n# درخواست: {text}\nprint('خطا در دسترسی به مدل‌های OpenAI')"
171
- save_to_db(text, language, error_code, error_msg, success=False)
172
- return error_msg, error_code
173
-
174
- # پاک‌سازی کد از markdown
175
- final_code = clean_code_output(response_content)
176
-
177
- if not final_code or final_code.strip() == "":
178
- final_code = f"# کد برای: {text}\n# زبان: {language}\nprint('خوش آمدید!')"
179
-
180
- # ذخیره در دیتابیس
181
- save_to_db(text, language, final_code, f"Model: {model_used}", success=True)
182
-
183
- logger.info("✅ Code generated and saved successfully")
184
- return f"✅ کد با موفقیت تولید شد (مدل: {model_used})", final_code
185
-
186
  except Exception as e:
187
  logger.error(f"❌ Code generation error: {e}")
188
- error_code = f"# خطا در تولید کد: {str(e)}\n# درخواست: {text}\n# زبان: {language}\nprint('متأسفانه خطایی رخ داد')"
189
- save_to_db(text, language, error_code, str(e), success=False)
190
- return f"❌ خطا: {str(e)}", error_code
191
-
192
- def clean_code_output(code_text):
193
- """پاک‌سازی کد از markdown و متن اضافی"""
194
- if not code_text:
195
- return ""
196
-
197
- # حذف markdown code blocks
198
- if "```" in code_text:
199
- import re
200
- # پیدا کردن همه بلاک‌های کد
201
- code_blocks = re.findall(r'```(?:\w+\n)?(.*?)```', code_text, re.DOTALL)
202
- if code_blocks:
203
- # انتخاب بزرگترین بلاک کد
204
- largest_block = max(code_blocks, key=len)
205
- return largest_block.strip()
206
-
207
- return code_text.strip()
208
 
209
- # تابع اصلی برای پردازش درخواست
210
- def process_request(user_input, language, show_history):
211
- logger.info(f"📨 Processing request - Language: {language}, Show History: {show_history}")
212
-
213
- if not user_input or not user_input.strip():
214
- return "❌ لطفاً توضیحی برای برنامه وارد کنید.", get_history() if show_history else "", ""
215
-
216
  try:
217
- # تولید کد
218
- status_message, generated_code = generate_code(user_input, language)
219
-
220
- # دریافت تاریخچه در صورت درخواست
221
  history = get_history() if show_history else ""
222
-
223
- logger.info("✅ Request processed successfully")
224
- return generated_code, history, status_message
225
-
226
  except Exception as e:
227
  logger.error(f"❌ Processing error: {e}")
228
- error_response = f"# متأسفانه خطایی رخ داد: {str(e)}\nprint('لطفاً مجدداً تلاش کنید')"
229
  history = get_history() if show_history else ""
230
- return error_response, history, f"خطا: {str(e)}"
231
 
232
  # رابط گرادیو
233
- def create_gradio_interface():
234
- with gr.Blocks(
235
- theme=gr.themes.Soft(),
236
- title="کریستوفر - دستیار کدنویسی",
237
- css="""
238
- .gradio-container {
239
- font-family: 'Tahoma', sans-serif;
240
- direction: rtl;
241
- }
242
- .status-success { color: #22c55e; font-weight: bold; }
243
- .status-error { color: #ef4444; font-weight: bold; }
244
- """
245
- ) as demo:
246
-
247
- gr.Markdown("""
248
- # 🤖 کریستوفر - دستیار هوشمند کدنویسی
249
- ### 🚀 با قدرت مدل‌های OpenAI
250
-
251
- توضیح برنامه‌ای که می‌خواهید را به فارسی وارد کنید و زبان برنامه‌نویسی مورد نظر را انتخاب کنید.
252
- """)
253
-
254
- with gr.Row():
255
- with gr.Column(scale=2):
256
- user_input = gr.Textbox(
257
- label="📝 توضیح برنامه به فارسی",
258
- placeholder="مثال: یک تابع برای محاسبه اعداد فیبوناچی تا عدد n",
259
- lines=4,
260
- max_lines=8
261
- )
262
-
263
- with gr.Row():
264
- language = gr.Dropdown(
265
- choices=["Python", "JavaScript", "Java", "C++", "C#", "Go", "Rust", "PHP", "TypeScript"],
266
- label="🔧 زبان برنامه‌نویسی",
267
- value="Python"
268
- )
269
-
270
- show_history = gr.Checkbox(
271
- label="📋 نمایش تاریخچه",
272
- value=False
273
- )
274
-
275
- generate_btn = gr.Button("🚀 تولید کد", variant="primary", size="lg")
276
-
277
- # نمایش وضعیت
278
- status_display = gr.Markdown("آماده برای تولید کد...")
279
-
280
- with gr.Row():
281
- with gr.Column(scale=3):
282
- code_output = gr.Code(
283
- label="💻 کد تولیدشده",
284
- language="python",
285
- interactive=False,
286
- show_label=True
287
- )
288
-
289
- with gr.Column(scale=2, visible=False) as history_column:
290
- history_output = gr.Markdown(
291
- label="📜 تاریخچه درخواست‌ها",
292
- value="تاریخچه‌ای موجود نیست."
293
- )
294
-
295
- # تنظیم رویدادها
296
- def update_interface(user_input, language, show_history):
297
- code, history, status = process_request(user_input, language, show_history)
298
-
299
- # تنظیم نمایش تاریخچه
300
- history_visibility = gr.update(visible=show_history)
301
-
302
- return (
303
- code, # کد تولیدشده
304
- history if show_history else "", # تاریخچه
305
- status, # وضعیت
306
- history_visibility # نمایش ستون تاریخچه
307
- )
308
-
309
- generate_btn.click(
310
- fn=update_interface,
311
- inputs=[user_input, language, show_history],
312
- outputs=[code_output, history_output, status_display, history_column]
313
- )
314
-
315
- show_history.change(
316
- fn=lambda x: gr.update(visible=x),
317
- inputs=[show_history],
318
- outputs=[history_column]
319
- )
320
-
321
- # مثال‌های نمونه
322
- gr.Markdown("""
323
- ### 💡 مثال‌های نمونه درخواست:
324
-
325
- 🔢 **ریاضی:** "یک تابع برای محاسبه فاکتوریل عدد"
326
- 📊 **داده:** "برنامه مرتب‌سازی لیست اعداد به صورت صعودی"
327
- 🎮 **بازی:** "یک بازی حدس عدد ساده"
328
- 📁 **فایل:** "تابعی برای خواندن و نوشتن فایل متنی"
329
- 🌐 **وب:** "یک صفحه HTML ساده با فرم ورودی"
330
- """)
331
-
332
- # نمایش آمار دیتابیس
333
- with gr.Row():
334
- stats_btn = gr.Button("📊 نمایش آمار", size="sm")
335
- stats_output = gr.Textbox(label="📈 آمار دیتابیس", visible=False)
336
-
337
- def show_stats():
338
- try:
339
- with sqlite3.connect(DB_PATH) as conn:
340
- cursor = conn.cursor()
341
- cursor.execute("SELECT COUNT(*) FROM code_history")
342
- total = cursor.fetchone()[0]
343
-
344
- cursor.execute("SELECT COUNT(*) FROM code_history WHERE success = 1")
345
- successful = cursor.fetchone()[0]
346
-
347
- cursor.execute("SELECT language, COUNT(*) FROM code_history GROUP BY language ORDER BY COUNT(*) DESC")
348
- lang_stats = cursor.fetchall()
349
-
350
- stats = f"📊 **آمار کلی:**\n"
351
- stats += f"🔢 **کل درخواست‌ها:** {total}\n"
352
- stats += f"✅ **موفق:** {successful}\n"
353
- stats += f"❌ **ناموفق:** {total - successful}\n\n"
354
- stats += f"🔧 **زبان‌های پربازدید:**\n"
355
-
356
- for lang, count in lang_stats:
357
- stats += f"• {lang}: {count} درخواست\n"
358
-
359
- return gr.update(value=stats, visible=True)
360
- except:
361
- return gr.update(value="خطا در نمایش آمار", visible=True)
362
-
363
- stats_btn.click(
364
- fn=show_stats,
365
- inputs=[],
366
- outputs=[stats_output]
367
- )
368
-
369
- return demo
370
 
371
- # تابع اصلی برنامه
372
- def main():
373
- logger.info("🚀 Starting Christopher - Code Generation Assistant")
374
-
375
  try:
376
- # مقداردهی اولیه دیتابیس
377
  init_db()
378
-
379
- # ایجاد رابط گرادیو
380
- demo = create_gradio_interface()
381
-
382
- logger.info("🌐 Launching Gradio interface")
383
- demo.launch(
384
- server_name="0.0.0.0",
385
- server_port=7860,
386
- share=False,
387
- show_error=True,
388
- show_api=False
 
 
 
389
  )
390
-
391
  except Exception as e:
392
- logger.error(f"❌ Application startup error: {e}")
393
- raise
394
-
395
- if __name__ == "__main__":
396
- main()
 
9
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
10
  logger = logging.getLogger(__name__)
11
 
12
+ # تنظیم API Key
13
  logger.info("Starting application setup")
14
+ openrouter_api_key = "qwen_key"
15
+ if not openrouter_api_key:
16
+ logger.error(" OPENROUTER_API_KEY not set")
17
+ raise ValueError("❌ OPENROUTER_API_KEY is required. For local run, set it as an environment variable. For Spaces, set it in Settings > Repository secrets > Add secret > Name: OPENROUTER_API_KEY.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # تنظیم کلاینت OpenAI برای OpenRouter
20
+ try:
21
+ client = OpenAI(
22
+ base_url="https://openrouter.ai/api/v1",
23
+ api_key=openrouter_api_key
24
+ )
25
+ # تست API Key
26
+ test_response = client.chat.completions.create(
27
+ model="qwen/qwen3-coder:free",
28
+ messages=[{"role": "user", "content": "test"}],
29
+ max_tokens=10,
30
+ extra_headers={
31
+ "HTTP-Referer": "https://my-christopher-app.com",
32
+ "X-Title": "Christopher Coding Assistant"
33
+ }
34
+ )
35
+ logger.info("✅ Initialized OpenAI client and API key validated for model qwen/qwen3-coder:free")
36
+ except Exception as e:
37
+ logger.error(f"❌ Failed to initialize OpenAI client or validate API key: {e}")
38
+ raise
39
 
40
  # ایجاد دیتابیس
41
  def init_db():
42
  logger.info("🗄️ Initializing database")
43
  try:
44
+ with sqlite3.connect("chris.db") as conn:
45
  cursor = conn.cursor()
46
  cursor.execute('''CREATE TABLE IF NOT EXISTS code_history (
47
  id INTEGER PRIMARY KEY AUTOINCREMENT,
 
56
  logger.info("✅ Database initialized successfully")
57
  except Exception as e:
58
  logger.error(f"❌ Database initialization error: {e}")
59
+ raise
60
 
61
  # ذخیره در دیتابیس
62
+ def save_to_memory(user_input, language, prompt, generated_code, success=True):
63
+ logger.info("Saving to database")
64
  try:
65
+ with sqlite3.connect("chris.db") as conn:
66
  cursor = conn.cursor()
67
+ cursor.execute('''INSERT INTO code_history (user_input, language, generated_code, prompt_used, timestamp, success)
68
+ VALUES (?, ?, ?, ?, ?, ?)''',
69
+ (user_input, language, generated_code, prompt, datetime.now().isoformat(), success))
 
 
70
  conn.commit()
71
+ logger.info("✅ Saved to database")
72
  except Exception as e:
73
  logger.error(f"❌ Database save error: {e}")
74
 
75
  # دریافت تاریخچه
76
+ def get_history():
77
+ logger.info("Retrieving history from database")
78
  try:
79
+ with sqlite3.connect("chris.db") as conn:
80
  cursor = conn.cursor()
81
+ cursor.execute("SELECT id, user_input, language, generated_code, prompt_used, timestamp, success FROM code_history ORDER BY timestamp DESC")
 
 
 
82
  rows = cursor.fetchall()
 
83
  if not rows:
84
+ return "هیچ تاریخچه‌ای موجود نیست."
85
+ history_text = "=== تاریخچه ===\n"
86
+ for row in rows:
87
+ history_text += f"ID: {row[0]}\n"
88
+ history_text += f"ورودی کاربر: {row[1]}\n"
89
+ history_text += f"زبان: {row[2]}\n"
90
+ history_text += f"پرامپت: {row[4] or 'بدون پرامپت'}\n"
91
+ history_text += f"کد تولیدشده: {row[3]}\n"
92
+ history_text += f"زمان: {row[5]}\n"
93
+ history_text += f"موفقیت: {'بله' if row[6] else 'خیر'}\n"
94
+ history_text += "-" * 50 + "\n"
 
 
95
  return history_text
 
96
  except Exception as e:
97
  logger.error(f"❌ History retrieval error: {e}")
98
+ return f"خطا در دریافت تاریخچه: {e}"
99
 
100
  # تولید کد
101
+ def generate_code(user_input, language):
102
+ logger.info(f"Processing input: {user_input}, language: {language}")
 
 
 
 
 
 
 
103
  try:
104
+ # پرامپت مستقیماً ورودی کاربر با زبان
105
+ prompt = f"{user_input} in {language}"
106
+ logger.info(f"Generated prompt: {prompt}")
107
+ response = client.chat.completions.create(
108
+ model="qwen/qwen3-coder:free",
109
+ messages=[
110
+ {"role": "system", "content": f"You are a coding assistant that generates complete and well-explained code in {language}."},
111
+ {"role": "user", "content": prompt}
112
+ ],
113
+ max_tokens=1024,
114
+ temperature=0.7,
115
+ top_p=0.8,
116
+ extra_headers={
117
+ "HTTP-Referer": "https://my-christopher-app.com",
118
+ "X-Title": "Christopher Coding Assistant"
119
+ },
120
+ extra_body={}
121
+ )
122
+ code_output = response.choices[0].message.content.strip()
123
+
124
+ # استخراج کد از خروجی (در صورت وجود بلاک کد)
125
+ lines = code_output.split('\n')
126
+ code = []
127
+ is_code = False
128
+ for line in lines:
129
+ if line.startswith("```"):
130
+ is_code = not is_code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  continue
132
+ elif is_code:
133
+ code.append(line)
134
+
135
+ final_code = "\n".join(code).strip() if code else code_output
136
+ if not final_code:
137
+ logger.warning("Generated code is empty")
138
+ final_code = "خطا: کد تولیدشده خالی است"
139
+ save_to_memory(user_input, language, prompt, final_code, success=False)
140
+ return prompt, final_code
141
+
142
+ logger.info(f"Generated code: {final_code}")
143
+ save_to_memory(user_input, language, prompt, final_code)
144
+ return prompt, final_code
 
 
 
 
 
 
145
  except Exception as e:
146
  logger.error(f"❌ Code generation error: {e}")
147
+ save_to_memory(user_input, language, prompt, str(e), success=False)
148
+ return prompt, f"خطا در تولید کد: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
+ # تابع اصلی
151
+ def christopher(user_input, language, show_history):
152
+ logger.info(f"Processing input: {user_input}, language: {language}, show_history: {show_history}")
 
 
 
 
153
  try:
154
+ prompt, generated_code = generate_code(user_input, language)
 
 
 
155
  history = get_history() if show_history else ""
156
+ return generated_code, history
 
 
 
157
  except Exception as e:
158
  logger.error(f"❌ Processing error: {e}")
 
159
  history = get_history() if show_history else ""
160
+ return f"خطا: {e}", history
161
 
162
  # رابط گرادیو
163
+ def gradio_ui(user_input, language, show_history):
164
+ code, history = christopher(user_input, language, show_history)
165
+ return code, history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ if __name__ == "__main__":
168
+ logger.info("Starting application")
 
 
169
  try:
 
170
  init_db()
171
+ logger.info("🚀 Launching Gradio interface")
172
+ iface = gr.Interface(
173
+ fn=gradio_ui,
174
+ inputs=[
175
+ gr.Textbox(label="توضیح برنامه به فارسی (مثال: یک تابع اعداد زوج)"),
176
+ gr.Dropdown(choices=["Python", "JavaScript", "Java", "C++"], label="زبان برنامه‌نویسی"),
177
+ gr.Checkbox(label="نمایش تاریخچه درخواست‌ها", value=False)
178
+ ],
179
+ outputs=[
180
+ gr.Textbox(label="کد تولیدشده"),
181
+ gr.Textbox(label="تاریخچه درخواست‌ها")
182
+ ],
183
+ title="کریستوفر - دستیار کدنویسی",
184
+ description="توضیح برنامه را به فارسی وارد کنید و زبان برنامه‌نویسی را انتخاب کنید. برای نمایش تاریخچه، گزینه مربوطه را تیک بزنید."
185
  )
186
+ iface.launch(server_name="0.0.0.0", server_port=7860)
187
  except Exception as e:
188
+ logger.error(f"❌ Startup error: {e}")
189
+ raise