File size: 15,305 Bytes
90233cc
c205f28
b94bfc6
b3a9447
b94bfc6
b3a9447
 
c205f28
 
733f738
b94bfc6
c205f28
b94bfc6
c205f28
82e7e6b
c205f28
 
 
 
 
 
 
 
 
 
 
 
 
82e7e6b
 
 
 
 
 
b94bfc6
c205f28
82e7e6b
 
 
c205f28
 
82e7e6b
 
 
 
b94bfc6
c205f28
82e7e6b
c205f28
 
 
 
 
 
82e7e6b
 
 
c205f28
 
 
 
82e7e6b
c205f28
 
 
 
0189427
c205f28
82e7e6b
c205f28
 
82e7e6b
733f738
82e7e6b
c205f28
82e7e6b
 
 
c205f28
82e7e6b
 
c205f28
 
 
 
 
 
 
 
 
 
b3a9447
82e7e6b
c205f28
 
733f738
c205f28
82e7e6b
c205f28
82e7e6b
c205f28
 
 
 
 
 
 
 
 
 
 
82e7e6b
 
c205f28
90233cc
c205f28
 
82e7e6b
c205f28
82e7e6b
 
c205f28
82e7e6b
c205f28
82e7e6b
 
 
c205f28
82e7e6b
c205f28
82e7e6b
c205f28
82e7e6b
 
 
c205f28
 
 
82e7e6b
c205f28
b3a9447
c205f28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b3a9447
 
c205f28
 
 
82e7e6b
c205f28
 
 
 
 
 
 
 
 
733f738
c205f28
 
 
 
 
 
 
 
82e7e6b
c205f28
82e7e6b
c205f28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b3a9447
c205f28
82e7e6b
c205f28
 
 
 
 
 
b3a9447
c205f28
 
 
 
 
 
b3a9447
c205f28
 
 
 
 
 
82e7e6b
c205f28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733f738
c205f28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

# app.py - نسخه کاملاً اصلاح شده
import pandas as pd
import numpy as np
import gradio as gr
import pickle
import warnings
import os

warnings.filterwarnings('ignore')

print("🚀 در حال راه‌اندازی سیستم بررسی نظرات...")

# ============ 1. بارگذاری داده‌ها ============
try:
    if os.path.exists('rew.csv'):
        df = pd.read_csv('rew.csv')
        print(f"✅ داده‌های واقعی بارگذاری شد: {len(df)} نمونه")
    else:
        df = pd.DataFrame({
            'des': ['محصول خوبی بود', 'کیفیت پایین'],
            'pos': [2, 1],
            'neg': [1, 3],
            'score': [4, 2]
        })
        print("⚠️ از داده‌های نمونه استفاده می‌شود")
except Exception as e:
    print(f"❌ خطا در بارگذاری داده‌ها: {e}")
    df = pd.DataFrame({
        'des': ['محصول خوبی بود', 'کیفیت پایین'],
        'pos': [2, 1],
        'neg': [1, 3],
        'score': [4, 2]
    })

# ============ 2. بارگذاری مدل BERT ============
try:
    from transformers import pipeline
    sen = pipeline('sentiment-analysis', 
                   model='HooshvareLab/bert-fa-base-uncased-sentiment-snappfood',
                   device=-1)
    print("✅ مدل BERT بارگذاری شد")
except Exception as e:
    print(f"⚠️ مدل BERT بارگذاری نشد: {e}")
    sen = None

# ============ 3. بارگذاری یا آموزش مدل Logistic Regression ============
try:
    if os.path.exists('trained_model.pkl'):
        with open('trained_model.pkl', 'rb') as f:
            model = pickle.load(f)
        print("✅ مدل Logistic Regression بارگذاری شد")
    else:
        raise FileNotFoundError("مدل ذخیره شده یافت نشد")
except:
    print("⚠️ آموزش مدل جدید...")
    from sklearn.linear_model import LogisticRegression
    model = LogisticRegression(random_state=42, max_iter=1000)
    # داده‌های آموزش
    X_train = [[1, 2, 1], [0, 1, 3], [1, 3, 1], [0, 2, 2], [1, 2, 2]]
    y_train = [1, 0, 1, 0, 1]
    model.fit(X_train, y_train)
    # ذخیره مدل
    with open('trained_model.pkl', 'wb') as f:
        pickle.dump(model, f)
    print("✅ مدل جدید آموزش و ذخیره شد")

# ============ 4. تابع تحلیل احساس ============
def analyze_sentiment(text):
    """تحلیل احساس متن"""
    if not text or not text.strip():
        return "📝 منتظر متن..."
    
    try:
        if sen is not None:
            result = sen(text[:200])[0]
            label = result['label']
            conf = result['score']
            return f"{'😊 مثبت' if label == 'HAPPY' else '😞 منفی'} (اطمینان: {conf:.1%})"
        else:
            text_low = text.lower()
            pos_words = ['عالی', 'خوب', 'ممتاز', 'عالیه', 'خوبه', 'قشنگ']
            neg_words = ['بد', 'ضعیف', 'خراب', 'بدم', 'بدیه', 'ناراضی']
            
            pos_count = sum(1 for w in pos_words if w in text_low)
            neg_count = sum(1 for w in neg_words if w in text_low)
            
            if pos_count > neg_count:
                return f"😊 مثبت ({pos_count} کلمه مثبت)"
            elif neg_count > pos_count:
                return f"😞 منفی ({neg_count} کلمه منفی)"
            else:
                return "😐 خنثی"
    except Exception as e:
        return f"⚠️ خطا در تحلیل: {str(e)}"

# ============ 5. تابع اصلی پیش‌بینی ============
def predict(review, strengths, weaknesses, rating):
    """پیش‌بینی و تصمیم‌گیری نهایی"""
    try:
        # تحلیل احساس متن
        if sen is not None and review.strip():
            try:
                sent_result = sen(review[:300])[0]
                des = 1 if sent_result['label'] == 'HAPPY' else 0
                sentiment_label = sent_result['label']
                sentiment_conf = sent_result['score']
            except:
                des = 1 if len(review) > 10 else 0
                sentiment_label = "مثبت" if des == 1 else "منفی"
                sentiment_conf = 0.5
        else:
            des = 1 if len(review) > 10 else 0


sentiment_label = "مثبت" if des == 1 else "منفی"
            sentiment_conf = 0.5
        
        # پیش‌بینی با مدل Logistic Regression
        features = np.array([[des, strengths, weaknesses]])
        pred = model.predict(features)[0]
        pred_proba = model.predict_proba(features)[0]
        
        # تصمیم‌گیری نهایی (طبق منطق اصلی شما)
        if pred == 1 and rating >= 3:
            result = "✅ نظر شما ثبت شد"
            color = "green"
            icon = "✅"
        elif pred == 1 and rating < 3:
            result = "❌ لطفاً امتیاز مناسب بدهید. نظر شما ثبت نشد."
            color = "red"
            icon = "❌"
        elif pred == 0 and rating < 3:
            result = "✅ نظر شما ثبت شد"
            color = "green"
            icon = "✅"
        else:  # pred == 0 and rating >= 3
            result = "❌ لطفاً امتیاز مناسب بدهید. نظر شما ثبت نشد."
            color = "red"
            icon = "❌"
        
        # ساخت گزارش HTML
        report = f"""
        <div style='border: 2px solid {color}; padding: 20px; border-radius: 10px; margin: 15px;'>
            <h3 style='color: {color}; text-align: center;'>{icon} {result}</h3>
            
            <hr style='border: 1px solid #ddd; margin: 15px 0;'>
            
            <h4 style='color: #333;'>📊 جزئیات تحلیل:</h4>
            
            <table style='width: 100%; border-collapse: collapse; font-size: 14px;'>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px; width: 40%;'><b>📝 نظر شما:</b></td>
                    <td style='padding: 10px;'>{review[:80]}{'...' if len(review) > 80 else ''}</td>
                </tr>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px;'><b>😊 تحلیل احساس:</b></td>
                    <td style='padding: 10px;'>{'مثبت 😊' if des == 1 else 'منفی 😞'} ({sentiment_conf:.1%})</td>
                </tr>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px;'><b>🔺 نقاط قوت:</b></td>
                    <td style='padding: 10px;'>{strengths} از ۳</td>
                </tr>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px;'><b>🔻 نقاط ضعف:</b></td>
                    <td style='padding: 10px;'>{weaknesses} از ۳</td>
                </tr>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px;'><b>⭐ امتیاز:</b></td>
                    <td style='padding: 10px;'>{rating} از ۵</td>
                </tr>
                <tr style='border-bottom: 1px solid #eee;'>
                    <td style='padding: 10px;'><b>🤖 تصمیم مدل:</b></td>
                    <td style='padding: 10px;'>{'تایید ✅' if pred == 1 else 'رد ❌'}</td>
                </tr>
                <tr>
                    <td style='padding: 10px;'><b>📈 اطمینان مدل:</b></td>
                    <td style='padding: 10px;'>{pred_proba[max(pred, 0)]:.1%}</td>
                </tr>
            </table>
            
            <div style='margin-top: 20px; padding: 12px; background-color: #f8f9fa; border-radius: 8px;'>
                <p style='margin: 0; font-size: 13px; color: #666;'>
                    <b>📋 نکته:</b> این سیستم بر اساس {len(df)} نظر آموزش دیده است.
                    ترکیب احساس متن، نقاط قوت/ضعف و امتیاز در تصمیم‌گیری تأثیر دارد.
                </p>
            </div>
        </div>
        """
        
        return report
        
    except Exception as e:
        return f"""
        <div style='border: 2px solid orange; padding: 20px; border-radius: 10px;'>
            <h3 style='color: orange;'>⚠️ خطا در پردازش</h3>
            <p>خطای زیر رخ داد:</p>
            <pre style='background-color: #f8f9fa; padding: 10px; border-radius: 5px; font-size: 12px;'>{str(e)}</pre>
            <p style='margin-top: 10px;'>لطفاً دوباره تلاش کنید.</p>
        </div>
        """


# ============ 6. ساخت رابط کاربری Gradio ============
with gr.Blocks(title="سیستم بررسی نظرات مشتریان", theme=gr.themes.Soft()) as demo:
    
    # عنوان اصلی
    gr.Markdown("""
    # 🛍️ سیستم بررسی و ثبت نظرات مشتریان
    نظر خود را وارد کنید تا سیستم هوشمند ما آن را تحلیل و تأیید کند.
    """)
    
    # ردیف اول: ورودی متن
    with gr.Row():
        with gr.Column(scale=2):
            # کادر متن
            text_input = gr.Textbox(
                label="👤 نظر خود را بنویسید",
                placeholder="مثال: کیفیت این محصول عالیه اما قیمتش کمی بالاست...",
                lines=4,
                max_lines=6
            )
            
            # نمایش تحلیل احساس
            sentiment_display = gr.Textbox(
                label="📊 تحلیل لحظه‌ای احساس",
                interactive=False,
                value="📝 منتظر نظر شما هستیم..."
            )
            
            # اتصال تغییرات متن به تحلیل احساس
            text_input.change(
                fn=analyze_sentiment,
                inputs=text_input,
                outputs=sentiment_display
            )
        
        with gr.Column(scale=1):
            # اطلاعات سیستم
            gr.Markdown(f"""
            ### 📊 اطلاعات سیستم
            • داده‌های آموزشی: {len(df)} نظر  
            • مدل احساس‌سنجی: {'فعال ✅' if sen else 'غیرفعال ⚠️'}  
            • مدل تصمیم‌گیری: Logistic Regression  
            • آخرین بروزرسانی: هم‌اکنون
            """)
    
    # ردیف دوم: تنظیمات
    with gr.Row():
        with gr.Column():
            strengths = gr.Slider(
                minimum=1,
                maximum=3,
                value=2,
                step=1,
                label="🔺 تعداد نقاط قوت",
                info="از ۱ تا ۳"
            )
        
        with gr.Column():
            weaknesses = gr.Slider(
                minimum=1,
                maximum=3,
                value=1,
                step=1,
                label="🔻 تعداد نقاط ضعف",
                info="از ۱ تا ۳"
            )
        
        with gr.Column():
            rating = gr.Radio(
                choices=[("۱ ستاره ⭐", 1), ("۲ ستاره ⭐⭐", 2), ("۳ ستاره ⭐⭐⭐", 3),
                        ("۴ ستاره ⭐⭐⭐⭐", 4), ("۵ ستاره ⭐⭐⭐⭐⭐", 5)],
                value=3,
                label="⭐ امتیاز کلی محصول",
                info="از ۱ (خیلی بد) تا ۵ (عالی)"
            )
    
    # دکمه ثبت
    with gr.Row():
        submit_btn = gr.Button(
            "📝 ارسال و تحلیل نظر",
            variant="primary",
            size="lg",
            scale=2
        )
    
    # خروجی
    with gr.Row():
        output_display = gr.HTML(
            label="🎯 نتیجه نهایی",
            value="<div style='text-align: center; color: #888; padding: 40px; font-size: 16px;'>نتیجه تحلیل نظر شما اینجا نمایش داده خواهد شد...</div>"
        )
    
    # اتصال دکمه
    submit_btn.click(
        fn=predict,
        inputs=[text_input, strengths, weaknesses, rating],
        outputs=output_display
    )
    
    # مثال‌های آماده
    with gr.Accordion("📋 کلیک کنید برای تست سریع (مثال‌های آماده)", open=False):
        examples = [
            ["این محصول واقعاً عالیه! کیفیت ساخت فوق‌العاده و بسته‌بندی شیکی داره.", 3, 1, 5],
            ["نسبت به قیمتش کیفیت پایینی داره و زود خراب شد.", 1, 3, 2],
            ["قیمت مناسبه اما رنگش با عکس فرق داره.", 2, 2, 3],
            ["بدترین خرید عمرم! اصلاً کار نمی‌کنه.", 1, 3, 1],
            ["ارزش پولش رو داره، عملکرد خوبیه.", 2, 1, 4]
        ]
        
        gr.Examples(
            examples=examples,
            inputs=[text_input, strengths, weaknesses, rating],
            outputs=output_display,
            fn=predict,
            label="برای تست سریع روی یک مثال کلیک کنید"
        )
    
    # راهنمای پایین صفحه
    with gr.Accordion("📖 راهنمای استفاده", open=False):


gr.Markdown("""
        ### نحوه استفاده:
        1. نظر خود را بنویسید: دیدگاه صادقانه خود را در مورد محصول وارد کنید.
        2. نقاط قوت و ضعف را مشخص کنید: تعداد نقاط مثبت و منفی محصول را انتخاب کنید.
        3. امتیاز دهید: از ۱ تا ۵ به محصول امتیاز دهید.
        4. ثبت کنید: دکمه "ارسال و تحلیل نظر" را بفشارید.
        
        ### منطق سیستم:
        - سیستم ابتدا احساس متن شما را با مدل BERT فارسی تحلیل می‌کند.
        - سپس با مدل Logistic Regression و بر اساس احساس متن، نقاط قوت/ضعف و امتیاز تصمیم می‌گیرد.
        - اگر مدل نظر را تأیید کند و امتیاز مناسب باشد، نظر ثبت می‌شود.
        
        ### رنگ‌های نتیجه:
        - ✅ سبز: نظر شما با موفقیت ثبت شد.
        - ❌ قرمز: نیاز به اصلاح دارد (معمولاً مشکل از امتیاز است).
        """)

# ============ 7. اجرای برنامه ============
if name == "main":
    print("\n" + "="*60)
    print("✅ سیستم آماده است!")
    print(f"📊 تعداد داده‌های آموزشی: {len(df)}")
    print(f"🤖 مدل احساس‌سنجی: {'فعال' if sen else 'غیرفعال'}")
    print(f"🧠 مدل Logistic Regression: فعال")
    print("🌐 در حال راه‌اندازی رابط کاربری...")
    print("="*60 + "\n")
    
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        share=False,
        debug=False,
        show_error=True
    )