Spaces:
Sleeping
Sleeping
Commit
·
de8770a
1
Parent(s):
43f3d48
Initial commit
Browse files
app.py
CHANGED
|
@@ -15,15 +15,29 @@ logger = logging.getLogger(__name__)
|
|
| 15 |
class ChristopherAI:
|
| 16 |
def __init__(self):
|
| 17 |
self.pipeline = None
|
|
|
|
|
|
|
| 18 |
self.db_path = "christopher.db"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
def setup_environment(self):
|
| 21 |
"""تنظیم محیط و احراز هویت"""
|
| 22 |
logger.info("Setting up environment")
|
| 23 |
|
| 24 |
# تنظیم timeout ها
|
| 25 |
-
os.environ["HF_HUB_ETAG_TIMEOUT"] = "
|
| 26 |
-
os.environ["HF_HUB_DOWNLOAD_TIMEOUT"] = "
|
| 27 |
|
| 28 |
# احراز هویت (اختیاری)
|
| 29 |
hf_token = os.getenv("HF_TOKEN", "")
|
|
@@ -35,56 +49,57 @@ class ChristopherAI:
|
|
| 35 |
logger.warning(f"HF authentication failed: {e}")
|
| 36 |
|
| 37 |
def load_model(self):
|
| 38 |
-
"""بارگذاری مدل
|
| 39 |
-
logger.info("Loading
|
| 40 |
|
| 41 |
-
|
| 42 |
-
#
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
#
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
model = AutoModelForCausalLM.from_pretrained(
|
| 51 |
-
model_name,
|
| 52 |
-
torch_dtype=torch.float32, # استفاده از float32 برای سازگاری بیشتر
|
| 53 |
-
low_cpu_mem_usage=True,
|
| 54 |
-
device_map=None # فقط CPU
|
| 55 |
-
)
|
| 56 |
-
|
| 57 |
-
# ایجاد pipeline ساده
|
| 58 |
-
self.pipeline = pipeline(
|
| 59 |
-
"text-generation",
|
| 60 |
-
model=model,
|
| 61 |
-
tokenizer=tokenizer,
|
| 62 |
-
device=-1, # فورس CPU
|
| 63 |
-
framework="pt"
|
| 64 |
-
)
|
| 65 |
-
|
| 66 |
-
logger.info("Lightweight model loaded successfully")
|
| 67 |
-
|
| 68 |
-
except Exception as e:
|
| 69 |
-
logger.error(f"Model loading failed: {e}")
|
| 70 |
-
# fallback به مدل سادهتر
|
| 71 |
try:
|
| 72 |
-
logger.info("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
self.pipeline = pipeline(
|
| 74 |
-
"text-generation",
|
| 75 |
-
model=
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
| 78 |
)
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
logger.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
def init_database(self):
|
| 87 |
-
"""ایجاد دیتابیس
|
| 88 |
logger.info("Initializing database")
|
| 89 |
try:
|
| 90 |
with sqlite3.connect(self.db_path) as conn:
|
|
@@ -100,12 +115,12 @@ class ChristopherAI:
|
|
| 100 |
)
|
| 101 |
''')
|
| 102 |
conn.commit()
|
| 103 |
-
logger.info("Database initialized")
|
| 104 |
except Exception as e:
|
| 105 |
-
logger.error(f"Database error: {e}")
|
| 106 |
|
| 107 |
def save_conversation(self, user_input, task_type, language, response):
|
| 108 |
-
"""ذخیره مکالمه"""
|
| 109 |
try:
|
| 110 |
with sqlite3.connect(self.db_path) as conn:
|
| 111 |
cursor = conn.cursor()
|
|
@@ -115,10 +130,10 @@ class ChristopherAI:
|
|
| 115 |
''', (user_input, task_type, language, response))
|
| 116 |
conn.commit()
|
| 117 |
except Exception as e:
|
| 118 |
-
logger.error(f"Save error: {e}")
|
| 119 |
|
| 120 |
-
def get_history(self, limit=
|
| 121 |
-
"""دریافت تاریخچه
|
| 122 |
try:
|
| 123 |
with sqlite3.connect(self.db_path) as conn:
|
| 124 |
cursor = conn.cursor()
|
|
@@ -131,135 +146,241 @@ class ChristopherAI:
|
|
| 131 |
|
| 132 |
records = cursor.fetchall()
|
| 133 |
if not records:
|
| 134 |
-
return "هیچ تاریخچهای یافت نشد."
|
| 135 |
|
| 136 |
-
history_text = "📋
|
| 137 |
for i, record in enumerate(records, 1):
|
| 138 |
user_input, task_type, lang, code, timestamp = record
|
| 139 |
-
history_text += f"**{i}. {timestamp}**\n"
|
| 140 |
-
history_text += f"
|
| 141 |
-
history_text += f"
|
| 142 |
-
history_text += "
|
|
|
|
| 143 |
|
| 144 |
return history_text
|
| 145 |
|
| 146 |
except Exception as e:
|
| 147 |
-
return f"خطا در دریافت تاریخچه: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
-
def
|
| 150 |
-
"""تولید کد با استفاده از
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
templates = {
|
| 152 |
"Python": {
|
| 153 |
-
"تولید کد جدید": f"""
|
| 154 |
|
| 155 |
def main():
|
| 156 |
-
|
| 157 |
-
|
| 158 |
pass
|
| 159 |
|
| 160 |
if __name__ == "__main__":
|
| 161 |
main()
|
| 162 |
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
{
|
|
|
|
| 171 |
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
|
|
|
| 180 |
{user_input}
|
| 181 |
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
| 188 |
},
|
|
|
|
| 189 |
"JavaScript": {
|
| 190 |
-
"تولید کد جدید": f"""
|
| 191 |
|
| 192 |
function main() {{
|
| 193 |
-
|
| 194 |
-
|
| 195 |
}}
|
| 196 |
|
|
|
|
| 197 |
main();
|
| 198 |
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
|
|
|
| 204 |
}
|
| 205 |
}
|
| 206 |
|
| 207 |
# انتخاب template مناسب
|
| 208 |
lang_templates = templates.get(programming_language, templates["Python"])
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
-
def
|
| 212 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
try:
|
| 214 |
-
if self.pipeline
|
| 215 |
-
|
| 216 |
-
result = self.generate_with_template(user_input, programming_language, task_type)
|
| 217 |
else:
|
| 218 |
-
|
| 219 |
-
if task_type == "تولید کد جدید":
|
| 220 |
-
prompt = f"Generate {programming_language} code for: {user_input}\n\n```{programming_language.lower()}\n"
|
| 221 |
-
elif task_type == "رفع اشکال کد":
|
| 222 |
-
prompt = f"Fix this {programming_language} code:\n{user_input}\n\nFixed code:\n```{programming_language.lower()}\n"
|
| 223 |
-
elif task_type == "توضیح کد":
|
| 224 |
-
prompt = f"Explain this {programming_language} code in Persian:\n{user_input}\n\nتوضیح:"
|
| 225 |
-
else:
|
| 226 |
-
prompt = f"Improve this {programming_language} code:\n{user_input}\n\nImproved code:\n```{programming_language.lower()}\n"
|
| 227 |
-
|
| 228 |
-
# تولید با پارامترهای محدود برای صرفهجویی در حافظه
|
| 229 |
-
response = self.pipeline(
|
| 230 |
-
prompt,
|
| 231 |
-
max_length=len(prompt.split()) + 150, # طول محدود
|
| 232 |
-
num_return_sequences=1,
|
| 233 |
-
temperature=0.7,
|
| 234 |
-
do_sample=True,
|
| 235 |
-
pad_token_id=50256 # GPT2 pad token
|
| 236 |
-
)
|
| 237 |
-
|
| 238 |
-
result = response[0]['generated_text'][len(prompt):].strip()
|
| 239 |
|
| 240 |
# ذخیره در دیتابیس
|
| 241 |
self.save_conversation(user_input, task_type, programming_language, result)
|
|
|
|
| 242 |
return result
|
| 243 |
|
| 244 |
except Exception as e:
|
| 245 |
-
logger.error(f"
|
| 246 |
-
|
| 247 |
-
return self.generate_with_template(user_input, programming_language, task_type)
|
| 248 |
-
|
| 249 |
-
def process_request(self, user_input, task_type, programming_language):
|
| 250 |
-
"""پردازش درخواست"""
|
| 251 |
-
if not user_input or not user_input.strip():
|
| 252 |
-
return "لطفاً متن درخواست خود را وارد کنید."
|
| 253 |
-
|
| 254 |
-
if task_type == "نمایش تاریخچه":
|
| 255 |
-
return self.get_history()
|
| 256 |
-
|
| 257 |
-
if not programming_language or not programming_language.strip():
|
| 258 |
-
programming_language = "Python" # پیشفرض
|
| 259 |
-
|
| 260 |
-
return self.generate_code(user_input, programming_language, task_type)
|
| 261 |
|
| 262 |
-
# ایجاد instance
|
| 263 |
christopher = ChristopherAI()
|
| 264 |
|
| 265 |
def gradio_interface(user_input, task_type, programming_language):
|
|
@@ -267,95 +388,135 @@ def gradio_interface(user_input, task_type, programming_language):
|
|
| 267 |
return christopher.process_request(user_input, task_type, programming_language)
|
| 268 |
|
| 269 |
def main():
|
| 270 |
-
"""تابع اصلی"""
|
| 271 |
try:
|
| 272 |
-
logger.info("🚀
|
| 273 |
|
| 274 |
-
# راهاندازی
|
| 275 |
christopher.setup_environment()
|
| 276 |
christopher.init_database()
|
| 277 |
christopher.load_model()
|
| 278 |
|
| 279 |
# آزادسازی حافظه
|
| 280 |
gc.collect()
|
|
|
|
|
|
|
| 281 |
|
| 282 |
-
logger.info("
|
| 283 |
|
| 284 |
-
# رابط
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
label="📝 درخواست یا کد شما",
|
| 290 |
-
placeholder="مثال: تابع محاسبه فاکتوریل بنویس",
|
| 291 |
-
lines=4
|
| 292 |
-
),
|
| 293 |
-
gr.Dropdown(
|
| 294 |
-
choices=[
|
| 295 |
-
"تولید کد جدید",
|
| 296 |
-
"رفع اشکال کد",
|
| 297 |
-
"توضیح کد",
|
| 298 |
-
"بهبود کد",
|
| 299 |
-
"نمایش تاریخچه"
|
| 300 |
-
],
|
| 301 |
-
label="🎯 نوع وظیفه",
|
| 302 |
-
value="تولید کد جدید"
|
| 303 |
-
),
|
| 304 |
-
gr.Textbox(
|
| 305 |
-
label="🔧 زبان برنامهنویسی",
|
| 306 |
-
placeholder="Python, JavaScript, Java, ...",
|
| 307 |
-
value="Python"
|
| 308 |
-
)
|
| 309 |
-
],
|
| 310 |
-
outputs=gr.Textbox(
|
| 311 |
-
label="📤 پاسخ کریستوفر",
|
| 312 |
-
lines=10,
|
| 313 |
-
show_copy_button=True
|
| 314 |
-
),
|
| 315 |
-
title="🤖 کریستوفر - دستیار کدنویسی (نسخه سبک)",
|
| 316 |
-
description="""
|
| 317 |
-
### 🚀 دستیار هوشمند کدنویسی برای Spaces رایگان
|
| 318 |
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
- 💻 تولید کد از توضیحات فارسی
|
| 321 |
-
- 🔧 رفع اشکالات کد
|
| 322 |
-
- 📚 توضیح کد به فارسی
|
| 323 |
-
- ⚡ بهبود کد
|
| 324 |
-
-
|
|
|
|
|
|
|
| 325 |
|
| 326 |
-
|
| 327 |
-
"""
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
-
logger.info("🌟
|
| 338 |
interface.launch(
|
| 339 |
server_name="0.0.0.0",
|
| 340 |
server_port=7860,
|
| 341 |
show_error=True,
|
| 342 |
share=False,
|
| 343 |
debug=False,
|
| 344 |
-
max_threads=
|
| 345 |
)
|
| 346 |
|
| 347 |
except Exception as e:
|
| 348 |
-
logger.error(f"❌
|
| 349 |
-
|
|
|
|
| 350 |
simple_interface = gr.Interface(
|
| 351 |
-
fn=lambda x, y, z: f"خطا در بارگذاری
|
| 352 |
inputs=[
|
| 353 |
-
gr.Textbox(label="درخواست"),
|
| 354 |
-
gr.Dropdown(choices=["تولید کد جدید"], value="تولید کد جدید"),
|
| 355 |
-
gr.
|
| 356 |
],
|
| 357 |
-
outputs=gr.Textbox(label="پاسخ"),
|
| 358 |
-
title="کریستوفر - حالت اضطراری"
|
|
|
|
| 359 |
)
|
| 360 |
simple_interface.launch(server_name="0.0.0.0", server_port=7860)
|
| 361 |
|
|
|
|
| 15 |
class ChristopherAI:
|
| 16 |
def __init__(self):
|
| 17 |
self.pipeline = None
|
| 18 |
+
self.tokenizer = None
|
| 19 |
+
self.model = None
|
| 20 |
self.db_path = "christopher.db"
|
| 21 |
+
self.supported_languages = {
|
| 22 |
+
"Python": {"ext": "py", "comment": "#", "multiline_start": '"""', "multiline_end": '"""'},
|
| 23 |
+
"JavaScript": {"ext": "js", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 24 |
+
"Java": {"ext": "java", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 25 |
+
"C++": {"ext": "cpp", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 26 |
+
"C": {"ext": "c", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 27 |
+
"PHP": {"ext": "php", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 28 |
+
"Go": {"ext": "go", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 29 |
+
"Rust": {"ext": "rs", "comment": "//", "multiline_start": "/*", "multiline_end": "*/"},
|
| 30 |
+
"HTML": {"ext": "html", "comment": "<!--", "multiline_start": "<!--", "multiline_end": "-->"},
|
| 31 |
+
"CSS": {"ext": "css", "comment": "/*", "multiline_start": "/*", "multiline_end": "*/"}
|
| 32 |
+
}
|
| 33 |
|
| 34 |
def setup_environment(self):
|
| 35 |
"""تنظیم محیط و احراز هویت"""
|
| 36 |
logger.info("Setting up environment")
|
| 37 |
|
| 38 |
# تنظیم timeout ها
|
| 39 |
+
os.environ["HF_HUB_ETAG_TIMEOUT"] = "180"
|
| 40 |
+
os.environ["HF_HUB_DOWNLOAD_TIMEOUT"] = "180"
|
| 41 |
|
| 42 |
# احراز هویت (اختیاری)
|
| 43 |
hf_token = os.getenv("HF_TOKEN", "")
|
|
|
|
| 49 |
logger.warning(f"HF authentication failed: {e}")
|
| 50 |
|
| 51 |
def load_model(self):
|
| 52 |
+
"""بارگذاری مدل بهینه برای فارسی"""
|
| 53 |
+
logger.info("Loading optimized model for Persian")
|
| 54 |
|
| 55 |
+
model_options = [
|
| 56 |
+
"microsoft/DialoGPT-medium", # ~355M parameters
|
| 57 |
+
"distilgpt2", # ~82M parameters
|
| 58 |
+
"microsoft/DialoGPT-small", # ~117M parameters
|
| 59 |
+
"gpt2" # ~124M parameters - fallback
|
| 60 |
+
]
|
| 61 |
+
|
| 62 |
+
for model_name in model_options:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
try:
|
| 64 |
+
logger.info(f"Trying to load: {model_name}")
|
| 65 |
+
|
| 66 |
+
# بارگذاری tokenizer
|
| 67 |
+
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 68 |
+
if self.tokenizer.pad_token is None:
|
| 69 |
+
self.tokenizer.pad_token = self.tokenizer.eos_token
|
| 70 |
+
|
| 71 |
+
# بارگذاری مدل با تنظیمات بهینه
|
| 72 |
+
self.model = AutoModelForCausalLM.from_pretrained(
|
| 73 |
+
model_name,
|
| 74 |
+
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
| 75 |
+
low_cpu_mem_usage=True,
|
| 76 |
+
device_map="auto" if torch.cuda.is_available() else None
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
# ایجاد pipeline
|
| 80 |
+
device = 0 if torch.cuda.is_available() else -1
|
| 81 |
self.pipeline = pipeline(
|
| 82 |
+
"text-generation",
|
| 83 |
+
model=self.model,
|
| 84 |
+
tokenizer=self.tokenizer,
|
| 85 |
+
device=device,
|
| 86 |
+
framework="pt",
|
| 87 |
+
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32
|
| 88 |
)
|
| 89 |
+
|
| 90 |
+
logger.info(f"Successfully loaded: {model_name}")
|
| 91 |
+
break
|
| 92 |
+
|
| 93 |
+
except Exception as e:
|
| 94 |
+
logger.error(f"Failed to load {model_name}: {e}")
|
| 95 |
+
continue
|
| 96 |
+
|
| 97 |
+
if self.pipeline is None:
|
| 98 |
+
logger.error("All models failed to load")
|
| 99 |
+
raise Exception("Could not load any model")
|
| 100 |
|
| 101 |
def init_database(self):
|
| 102 |
+
"""ایجاد دیتابیس"""
|
| 103 |
logger.info("Initializing database")
|
| 104 |
try:
|
| 105 |
with sqlite3.connect(self.db_path) as conn:
|
|
|
|
| 115 |
)
|
| 116 |
''')
|
| 117 |
conn.commit()
|
| 118 |
+
logger.info("Database initialized successfully")
|
| 119 |
except Exception as e:
|
| 120 |
+
logger.error(f"Database initialization error: {e}")
|
| 121 |
|
| 122 |
def save_conversation(self, user_input, task_type, language, response):
|
| 123 |
+
"""ذخیره مکالمه در دیتابیس"""
|
| 124 |
try:
|
| 125 |
with sqlite3.connect(self.db_path) as conn:
|
| 126 |
cursor = conn.cursor()
|
|
|
|
| 130 |
''', (user_input, task_type, language, response))
|
| 131 |
conn.commit()
|
| 132 |
except Exception as e:
|
| 133 |
+
logger.error(f"Save conversation error: {e}")
|
| 134 |
|
| 135 |
+
def get_history(self, limit=10):
|
| 136 |
+
"""دریافت تاریخچه مکالمات"""
|
| 137 |
try:
|
| 138 |
with sqlite3.connect(self.db_path) as conn:
|
| 139 |
cursor = conn.cursor()
|
|
|
|
| 146 |
|
| 147 |
records = cursor.fetchall()
|
| 148 |
if not records:
|
| 149 |
+
return "📋 هیچ تاریخچهای یافت نشد."
|
| 150 |
|
| 151 |
+
history_text = "📋 **تاریخچه درخواستهای اخیر:**\n\n"
|
| 152 |
for i, record in enumerate(records, 1):
|
| 153 |
user_input, task_type, lang, code, timestamp = record
|
| 154 |
+
history_text += f"**{i}. {timestamp.split('.')[0]}**\n"
|
| 155 |
+
history_text += f"🔹 **نوع وظیفه:** {task_type}\n"
|
| 156 |
+
history_text += f"🔹 **زبان:** {lang}\n"
|
| 157 |
+
history_text += f"🔹 **درخواست:** {user_input[:100]}{'...' if len(user_input) > 100 else ''}\n"
|
| 158 |
+
history_text += "─" * 50 + "\n\n"
|
| 159 |
|
| 160 |
return history_text
|
| 161 |
|
| 162 |
except Exception as e:
|
| 163 |
+
return f"❌ خطا در دریافت تاریخچه: {str(e)}"
|
| 164 |
+
|
| 165 |
+
def create_persian_prompt(self, user_input, programming_language, task_type):
|
| 166 |
+
"""ایجاد prompt فارسی برای مدل"""
|
| 167 |
+
|
| 168 |
+
lang_info = self.supported_languages.get(programming_language, self.supported_languages["Python"])
|
| 169 |
+
|
| 170 |
+
if task_type == "تولید کد جدید":
|
| 171 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. لطفاً برای درخواست زیر کد {programming_language} بنویسید:
|
| 172 |
+
|
| 173 |
+
درخواست: {user_input}
|
| 174 |
+
|
| 175 |
+
کد {programming_language}:
|
| 176 |
+
```{programming_language.lower()}
|
| 177 |
+
"""
|
| 178 |
+
|
| 179 |
+
elif task_type == "رفع اشکال کد":
|
| 180 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. کد زیر را بررسی کرده و اشکالات آن را برطرف کنید:
|
| 181 |
+
|
| 182 |
+
کد {programming_language} با مشکل:
|
| 183 |
+
{user_input}
|
| 184 |
+
|
| 185 |
+
کد اصلاح شده:
|
| 186 |
+
```{programming_language.lower()}
|
| 187 |
+
"""
|
| 188 |
+
|
| 189 |
+
elif task_type == "توضیح کد":
|
| 190 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. کد زیر را به زبان فارسی توضیح دهید:
|
| 191 |
+
|
| 192 |
+
کد {programming_language}:
|
| 193 |
+
{user_input}
|
| 194 |
+
|
| 195 |
+
توضیح به فارسی:
|
| 196 |
+
"""
|
| 197 |
+
|
| 198 |
+
elif task_type == "بهبود کد":
|
| 199 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. کد زیر را بهبود دهید و بهینهتر کنید:
|
| 200 |
+
|
| 201 |
+
کد {programming_language} اولیه:
|
| 202 |
+
{user_input}
|
| 203 |
+
|
| 204 |
+
کد بهبود یافته:
|
| 205 |
+
```{programming_language.lower()}
|
| 206 |
+
"""
|
| 207 |
+
|
| 208 |
+
elif task_type == "اضافه کردن قابلیت":
|
| 209 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. به کد زیر قابلیت جدید اضافه کنید:
|
| 210 |
+
|
| 211 |
+
کد {programming_language} موجود:
|
| 212 |
+
{user_input}
|
| 213 |
+
|
| 214 |
+
کد با قابلیت جدید:
|
| 215 |
+
```{programming_language.lower()}
|
| 216 |
+
"""
|
| 217 |
+
|
| 218 |
+
else: # تحلیل کد
|
| 219 |
+
prompt = f"""شما یک برنامهنویس حرفهای هستید. کد زیر را تحلیل کرده و نقاط قوت و ضعف آن را بیان کنید:
|
| 220 |
+
|
| 221 |
+
کد {programming_language}:
|
| 222 |
+
{user_input}
|
| 223 |
+
|
| 224 |
+
تحلیل کد:
|
| 225 |
+
"""
|
| 226 |
+
|
| 227 |
+
return prompt
|
| 228 |
|
| 229 |
+
def generate_code_with_model(self, user_input, programming_language, task_type):
|
| 230 |
+
"""تولید کد با استفاده از مدل"""
|
| 231 |
+
try:
|
| 232 |
+
prompt = self.create_persian_prompt(user_input, programming_language, task_type)
|
| 233 |
+
|
| 234 |
+
# تنظیمات تولید
|
| 235 |
+
generation_kwargs = {
|
| 236 |
+
"max_new_tokens": 300,
|
| 237 |
+
"temperature": 0.7,
|
| 238 |
+
"do_sample": True,
|
| 239 |
+
"top_p": 0.9,
|
| 240 |
+
"top_k": 50,
|
| 241 |
+
"repetition_penalty": 1.1,
|
| 242 |
+
"pad_token_id": self.tokenizer.eos_token_id,
|
| 243 |
+
"num_return_sequences": 1
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
# تولید پاسخ
|
| 247 |
+
response = self.pipeline(prompt, **generation_kwargs)
|
| 248 |
+
generated_text = response[0]['generated_text']
|
| 249 |
+
|
| 250 |
+
# استخراج پاسخ (حذف prompt از ابتدا)
|
| 251 |
+
result = generated_text[len(prompt):].strip()
|
| 252 |
+
|
| 253 |
+
# پردازش و تمیز کردن پاسخ
|
| 254 |
+
if "```" in result:
|
| 255 |
+
# اگر کد در markdown باشد، آن را استخراج کن
|
| 256 |
+
parts = result.split("```")
|
| 257 |
+
if len(parts) > 2:
|
| 258 |
+
result = parts[1].strip()
|
| 259 |
+
if result.startswith(programming_language.lower()):
|
| 260 |
+
result = result[len(programming_language.lower()):].strip()
|
| 261 |
+
|
| 262 |
+
return result if result else "متأسفانه نتوانستم پاسخ مناسبی تولید کنم."
|
| 263 |
+
|
| 264 |
+
except Exception as e:
|
| 265 |
+
logger.error(f"Model generation error: {e}")
|
| 266 |
+
return self.generate_fallback_response(user_input, programming_language, task_type)
|
| 267 |
+
|
| 268 |
+
def generate_fallback_response(self, user_input, programming_language, task_type):
|
| 269 |
+
"""تولید پاسخ جایگزین در صورت خرابی مدل"""
|
| 270 |
+
lang_info = self.supported_languages.get(programming_language, self.supported_languages["Python"])
|
| 271 |
+
|
| 272 |
templates = {
|
| 273 |
"Python": {
|
| 274 |
+
"تولید کد جدید": f"""{lang_info['comment']} کد Python برای: {user_input}
|
| 275 |
|
| 276 |
def main():
|
| 277 |
+
{lang_info['comment']} {user_input}
|
| 278 |
+
{lang_info['comment']} TODO: پیادهسازی منطق مورد نیاز
|
| 279 |
pass
|
| 280 |
|
| 281 |
if __name__ == "__main__":
|
| 282 |
main()
|
| 283 |
|
| 284 |
+
{lang_info['multiline_start']}
|
| 285 |
+
توضیح:
|
| 286 |
+
- این یک قالب پایه برای شروع کدنویسی است
|
| 287 |
+
- لطفاً منطق مناسب را جایگزین کنید
|
| 288 |
+
- از بهترین شیوههای Python استفاده کنید
|
| 289 |
+
{lang_info['multiline_end']}""",
|
| 290 |
+
|
| 291 |
+
"رفع اشکال کد": f"""{lang_info['comment']} بررسی کد برای رفع اشکال:
|
| 292 |
+
{lang_info['comment']} کد اصلی: {user_input}
|
| 293 |
|
| 294 |
+
{lang_info['multiline_start']}
|
| 295 |
+
نکات بررسی:
|
| 296 |
+
1. syntax و indentation
|
| 297 |
+
2. نامگذاری متغیرها
|
| 298 |
+
3. import های مورد نیاز
|
| 299 |
+
4. منطق الگوریتم
|
| 300 |
+
5. مدیریت خطا
|
| 301 |
+
{lang_info['multiline_end']}""",
|
| 302 |
+
|
| 303 |
+
"توضیح کد": f"""{lang_info['multiline_start']}
|
| 304 |
+
توضیح کد Python:
|
| 305 |
|
| 306 |
+
کد مورد بررسی:
|
| 307 |
{user_input}
|
| 308 |
|
| 309 |
+
تحلیل:
|
| 310 |
+
- هدف: [توضیح عملکرد کلی]
|
| 311 |
+
- ورودی: [نوع و توضیح ورودیها]
|
| 312 |
+
- خروجی: [نوع و توضیح خروجیها]
|
| 313 |
+
- پیچیدگی زمانی: [Big O notation]
|
| 314 |
+
- پیچیدگی فضایی: [استفاده از حافظه]
|
| 315 |
+
- نکات مهم: [نکات خاص کد]
|
| 316 |
+
{lang_info['multiline_end']}"""
|
| 317 |
},
|
| 318 |
+
|
| 319 |
"JavaScript": {
|
| 320 |
+
"تولید کد جدید": f"""{lang_info['comment']} کد JavaScript برای: {user_input}
|
| 321 |
|
| 322 |
function main() {{
|
| 323 |
+
{lang_info['comment']} {user_input}
|
| 324 |
+
{lang_info['comment']} TODO: پیادهسازی منطق مورد نیاز
|
| 325 |
}}
|
| 326 |
|
| 327 |
+
{lang_info['comment']} اجرای تابع
|
| 328 |
main();
|
| 329 |
|
| 330 |
+
{lang_info['multiline_start']}
|
| 331 |
+
توضیح:
|
| 332 |
+
- این یک قالب پایه برای شروع کدنویسی JavaScript است
|
| 333 |
+
- از ES6+ features استفاده کنید
|
| 334 |
+
- کد را مدولار و خوانا نگه دارید
|
| 335 |
+
{lang_info['multiline_end']}""",
|
| 336 |
}
|
| 337 |
}
|
| 338 |
|
| 339 |
# انتخاب template مناسب
|
| 340 |
lang_templates = templates.get(programming_language, templates["Python"])
|
| 341 |
+
default_template = f"""{lang_info['comment']} کد {programming_language} برای: {user_input}
|
| 342 |
+
|
| 343 |
+
{lang_info['comment']} TODO: پیادهسازی کد مناسب
|
| 344 |
+
|
| 345 |
+
{lang_info['multiline_start']}
|
| 346 |
+
این یک قالب پایه است.
|
| 347 |
+
لطفاً کد مناسب را بر اساس درخواست خود پیادهسازی کنید.
|
| 348 |
+
{lang_info['multiline_end']}"""
|
| 349 |
+
|
| 350 |
+
return lang_templates.get(task_type, default_template)
|
| 351 |
|
| 352 |
+
def process_request(self, user_input, task_type, programming_language):
|
| 353 |
+
"""پردازش درخواست کاربر"""
|
| 354 |
+
|
| 355 |
+
# بررسی ورودی
|
| 356 |
+
if not user_input or not user_input.strip():
|
| 357 |
+
return "⚠️ لطفاً متن درخواست خود را وارد کنید."
|
| 358 |
+
|
| 359 |
+
# نمایش تاریخچه
|
| 360 |
+
if task_type == "نمایش تاریخچه":
|
| 361 |
+
return self.get_history()
|
| 362 |
+
|
| 363 |
+
# تنظیم زبان پیشفرض
|
| 364 |
+
if not programming_language or programming_language not in self.supported_languages:
|
| 365 |
+
programming_language = "Python"
|
| 366 |
+
|
| 367 |
+
# تولید پاسخ
|
| 368 |
try:
|
| 369 |
+
if self.pipeline:
|
| 370 |
+
result = self.generate_code_with_model(user_input, programming_language, task_type)
|
|
|
|
| 371 |
else:
|
| 372 |
+
result = self.generate_fallback_response(user_input, programming_language, task_type)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
|
| 374 |
# ذخیره در دیتابیس
|
| 375 |
self.save_conversation(user_input, task_type, programming_language, result)
|
| 376 |
+
|
| 377 |
return result
|
| 378 |
|
| 379 |
except Exception as e:
|
| 380 |
+
logger.error(f"Request processing error: {e}")
|
| 381 |
+
return f"❌ خطا در پردازش درخواست: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
|
| 383 |
+
# ایجاد instance global
|
| 384 |
christopher = ChristopherAI()
|
| 385 |
|
| 386 |
def gradio_interface(user_input, task_type, programming_language):
|
|
|
|
| 388 |
return christopher.process_request(user_input, task_type, programming_language)
|
| 389 |
|
| 390 |
def main():
|
| 391 |
+
"""تابع اصلی برنامه"""
|
| 392 |
try:
|
| 393 |
+
logger.info("🚀 راهاندازی کریستوفر - دستیار کدنویسی فارسی")
|
| 394 |
|
| 395 |
+
# راهاندازی اولیه
|
| 396 |
christopher.setup_environment()
|
| 397 |
christopher.init_database()
|
| 398 |
christopher.load_model()
|
| 399 |
|
| 400 |
# آزادسازی حافظه
|
| 401 |
gc.collect()
|
| 402 |
+
if torch.cuda.is_available():
|
| 403 |
+
torch.cuda.empty_cache()
|
| 404 |
|
| 405 |
+
logger.info("✅ راهاندازی کامل شد")
|
| 406 |
|
| 407 |
+
# ایجاد رابط Gradio
|
| 408 |
+
with gr.Blocks(
|
| 409 |
+
theme=gr.themes.Soft(),
|
| 410 |
+
title="کریستوفر - دستیار کدنویسی فارسی"
|
| 411 |
+
) as interface:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
|
| 413 |
+
gr.Markdown("""
|
| 414 |
+
# 🤖 کریستوفر - دستیار هوشمند کدنویسی
|
| 415 |
+
### 🇮🇷 پشتیبانی کامل از زبان فارسی
|
| 416 |
+
|
| 417 |
+
**قابلیتهای کریستوفر:**
|
| 418 |
- 💻 تولید کد از توضیحات فارسی
|
| 419 |
+
- 🔧 رفع اشکالات و دیباگ کد
|
| 420 |
+
- 📚 توضیح کد به زبان فارسی
|
| 421 |
+
- ⚡ بهبود و بهینهسازی کد
|
| 422 |
+
- 🔄 اضافه کردن قابلیتهای جدید
|
| 423 |
+
- 🔍 تحلیل و بررسی کد
|
| 424 |
+
- 📋 ذخیره و مشاهده تاریخچه
|
| 425 |
|
| 426 |
+
**زبانهای پشتیبانی شده:** Python, JavaScript, Java, C++, C, PHP, Go, Rust, HTML, CSS
|
| 427 |
+
""")
|
| 428 |
+
|
| 429 |
+
with gr.Row():
|
| 430 |
+
with gr.Column(scale=2):
|
| 431 |
+
user_input = gr.Textbox(
|
| 432 |
+
label="📝 درخواست شما (به فارسی)",
|
| 433 |
+
placeholder="مثال: یک تابع برای محاسبه فاکتوریل بنویس که از recursion استفاده کند",
|
| 434 |
+
lines=4,
|
| 435 |
+
max_lines=8
|
| 436 |
+
)
|
| 437 |
+
|
| 438 |
+
with gr.Row():
|
| 439 |
+
task_type = gr.Dropdown(
|
| 440 |
+
choices=[
|
| 441 |
+
"تولید کد جدید",
|
| 442 |
+
"رفع اشکال کد",
|
| 443 |
+
"توضیح کد",
|
| 444 |
+
"بهبود کد",
|
| 445 |
+
"اضافه کردن قابلیت",
|
| 446 |
+
"تحلیل کد",
|
| 447 |
+
"نمایش تاریخچه"
|
| 448 |
+
],
|
| 449 |
+
label="🎯 نوع وظیفه",
|
| 450 |
+
value="تولید کد جدید"
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
programming_language = gr.Dropdown(
|
| 454 |
+
choices=list(christopher.supported_languages.keys()),
|
| 455 |
+
label="💾 زبان برنامهنویسی",
|
| 456 |
+
value="Python"
|
| 457 |
+
)
|
| 458 |
+
|
| 459 |
+
submit_btn = gr.Button("🚀 اجرا", variant="primary", size="lg")
|
| 460 |
+
|
| 461 |
+
with gr.Column(scale=3):
|
| 462 |
+
output = gr.Textbox(
|
| 463 |
+
label="📤 پاسخ کریستوفر",
|
| 464 |
+
lines=15,
|
| 465 |
+
max_lines=25,
|
| 466 |
+
show_copy_button=True,
|
| 467 |
+
container=True
|
| 468 |
+
)
|
| 469 |
+
|
| 470 |
+
# مثالهایی برای کاربران
|
| 471 |
+
gr.Examples(
|
| 472 |
+
examples=[
|
| 473 |
+
["یک تابع برای مرتبسازی لیست اعداد به روش bubble sort بنویس", "تولید کد جدید", "Python"],
|
| 474 |
+
["function factorial(n) {\n if (n <= 1) return 1;\n return n * factorial(n-1);\n}", "توضیح کد", "JavaScript"],
|
| 475 |
+
["def add(a, b):\nreturn a + b\n\nprint add(5, 3)", "رفع اشکال کد", "Python"],
|
| 476 |
+
["یک کلاس Calculator با عملیات پایه ریاضی بساز", "تولید کد جدید", "Java"],
|
| 477 |
+
["", "نمایش تاریخچه", ""]
|
| 478 |
+
],
|
| 479 |
+
inputs=[user_input, task_type, programming_language]
|
| 480 |
+
)
|
| 481 |
+
|
| 482 |
+
# اتصال دکمه submit
|
| 483 |
+
submit_btn.click(
|
| 484 |
+
fn=gradio_interface,
|
| 485 |
+
inputs=[user_input, task_type, programming_language],
|
| 486 |
+
outputs=output
|
| 487 |
+
)
|
| 488 |
+
|
| 489 |
+
# اجرای خودکار با Enter
|
| 490 |
+
user_input.submit(
|
| 491 |
+
fn=gradio_interface,
|
| 492 |
+
inputs=[user_input, task_type, programming_language],
|
| 493 |
+
outputs=output
|
| 494 |
+
)
|
| 495 |
|
| 496 |
+
logger.info("🌟 راهاندازی رابط کاربری")
|
| 497 |
interface.launch(
|
| 498 |
server_name="0.0.0.0",
|
| 499 |
server_port=7860,
|
| 500 |
show_error=True,
|
| 501 |
share=False,
|
| 502 |
debug=False,
|
| 503 |
+
max_threads=4
|
| 504 |
)
|
| 505 |
|
| 506 |
except Exception as e:
|
| 507 |
+
logger.error(f"❌ خطا در راهاندازی: {e}")
|
| 508 |
+
|
| 509 |
+
# رابط اضطراری
|
| 510 |
simple_interface = gr.Interface(
|
| 511 |
+
fn=lambda x, y, z: f"⚠️ خطا در بارگذاری مدل.\n\nدرخواست شما: {x}\nنوع وظیفه: {y}\nزبان: {z}\n\nلطفاً دوباره تلاش کنید.",
|
| 512 |
inputs=[
|
| 513 |
+
gr.Textbox(label="📝 درخواست", placeholder="درخواست خود را وارد کنید"),
|
| 514 |
+
gr.Dropdown(choices=["تولید کد جدید"], value="تولید کد جدید", label="🎯 نوع وظیفه"),
|
| 515 |
+
gr.Dropdown(choices=["Python"], value="Python", label="💾 زبان")
|
| 516 |
],
|
| 517 |
+
outputs=gr.Textbox(label="📤 پاسخ", lines=10),
|
| 518 |
+
title="🤖 کریستوفر - حالت اضطراری",
|
| 519 |
+
description="مدل در حال بارگذاری است. لطفاً کمی صبر کنید."
|
| 520 |
)
|
| 521 |
simple_interface.launch(server_name="0.0.0.0", server_port=7860)
|
| 522 |
|