File size: 6,705 Bytes
fd21fa2
b7764cf
 
 
 
 
 
 
 
fc39101
b7764cf
 
 
bd29fc5
b7764cf
a94ff47
b7764cf
bd29fc5
b7764cf
 
 
bd29fc5
b7764cf
 
 
 
 
 
 
bd29fc5
b7764cf
 
 
 
 
 
bd29fc5
fc39101
b7764cf
 
 
 
 
 
 
 
 
fc39101
b7764cf
 
 
 
 
 
 
 
fc39101
b7764cf
 
 
fd21fa2
b7764cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd21fa2
 
b7764cf
 
fc39101
b7764cf
fc39101
b7764cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fc39101
b7764cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fc39101
b7764cf
 
 
fc39101
b7764cf
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
import os
import re
import gradio as gr
from langchain_groq import ChatGroq
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter

embeddings = HuggingFaceEmbeddings(model_name="heydariAI/persian-embeddings")
vector_store = InMemoryVectorStore(embeddings)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
model = ChatGroq(api_key="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", model_name="deepseek-r1-distill-llama-70b")

chat_history = [] 

PRICE_PER_TOKEN = 0.00001  

def count_tokens(text):
    """تخمین تعداد توکن‌های متن."""
    return len(text.split())

def calculate_price(input_text, output_text):
    """محاسبه هزینه بر اساس تعداد توکن‌ها."""
    input_tokens = count_tokens(input_text)
    output_tokens = count_tokens(output_text)
    total_tokens = input_tokens + output_tokens
    total_price = total_tokens * PRICE_PER_TOKEN
    return total_tokens, f"{total_price:.6f} دلار"

def process_file(file_path):
    """پردازش فایل و بازگرداندن محتوای آن."""
    if not file_path:
        return None

    file_extension = os.path.splitext(file_path)[1].lower()

    try:
        if file_extension == ".pdf":
            from pypdf import PdfReader
            reader = PdfReader(file_path)
            return "\n".join(page.extract_text() for page in reader.pages)
        elif file_extension == ".txt":
            with open(file_path, "r", encoding="utf-8") as f:
                return f.read()
        else:
            raise ValueError(f"فرمت فایل پشتیبانی نمی‌شود: {file_extension}")
    except Exception as e:
        raise RuntimeError(f"خطا در پردازش فایل: {str(e)}")


def remove_think_sections(response_text):
    """حذف بخش‌های که با <think> شروع و با </think> تمام می‌شوند."""

    cleaned_text = re.sub(r"<think>.*?</think>", "", response_text, flags=re.DOTALL)
    return cleaned_text

def answer_query(query, file_path, summarize, tone):
    """پاسخ به سوالات کاربر با تنظیم لحن و محاسبه هزینه توکن."""
    global chat_history
    try:
        file_content = process_file(file_path) if file_path else None
        if file_content:
            file_docs = [Document(page_content=file_content, metadata={"source": "uploaded_file"})]
            file_splits = text_splitter.split_documents(file_docs)
            vector_store.add_documents(file_splits)

        retrieved_docs = vector_store.similarity_search(query, k=2)
        knowledge = "\n\n".join(doc.page_content for doc in retrieved_docs)

        tone_prompts = {
            "رسمی": "پاسخ را با لحنی رسمی و مودبانه ارائه کن.",
            "محاوره‌ای": "پاسخ را به صورت دوستانه و غیررسمی ارائه کن.",
            "علمی": "پاسخ را با ذکر منابع علمی و استدلال‌های منطقی ارائه کن.",
            "طنزآمیز": "پاسخ را با لحنی طنزآمیز و سرگرم‌کننده ارائه کن.",
        }
        tone_instruction = tone_prompts.get(tone, "پاسخ را به زبان فارسی ارائه کن.")

        prompt = (
            f"شما ParvizGPT هستید، یک دستیار هوش مصنوعی که توسط امیر مهدی پرویز ساخته شده است. "
            f"همیشه به فارسی پاسخ دهید. {tone_instruction} "
            f"\n\nاطلاعات مرتبط:\n{knowledge}\n\nسوال: {query}\nپاسخ:"
        )

        response = model.invoke(prompt)
        response_text = response.content

        cleaned_response = remove_think_sections(response_text)

        chat_history.append((query, cleaned_response))  

        total_tokens, price = calculate_price(prompt, cleaned_response)

        summary = summarize_chat() if summarize else "خلاصه‌سازی غیرفعال است."

        return cleaned_response, summary, total_tokens, price

    except Exception as e:
        return f"خطا: {str(e)}", "", 0, "0 دلار"

def summarize_chat():
    """خلاصه‌سازی مکالمات اخیر."""
    chat_text = "\n".join([f"پرسش: {q}\nپاسخ: {a}" for q, a in chat_history])  
    summary_prompt = f"یک خلاصه کوتاه و دقیق از مکالمه زیر ارائه کن:\n\n{chat_text}\n\nخلاصه:"
    summary_response = model.invoke(summary_prompt)
    return summary_response.content

def chat_with_bot(query, file, summarize, tone):
    """رابط Gradio برای چت."""
    file_path = file.name if file else None
    response, summary, total_tokens, price = answer_query(query, file_path, summarize, tone)
    return response, summary, total_tokens, price

with gr.Blocks() as demo:
    gr.Markdown("## 🤖 Parviz GPT")
    gr.Markdown("**یک فایل (PDF یا TXT) آپلود کنید و سوال خود را بپرسید.**")
    
    with gr.Column():

        chat_output = gr.Textbox(label="📝 تاریخچه چت", interactive=False, lines=10)
        summary_output = gr.Textbox(label="📌 خلاصه مکالمه", interactive=False)

        query_input = gr.Textbox(label="❓ سوال خود را وارد کنید", placeholder="مثلاً: کی تو را ساخته است؟")

        with gr.Row():
            summarize_checkbox = gr.Checkbox(label="📌 خلاصه‌ساز را فعال کن")
            submit_button = gr.Button("🚀 ارسال")
            tone_dropdown = gr.Dropdown(label="🎭 انتخاب لحن پاسخ", choices=["رسمی", "محاوره‌ای", "علمی", "طنزآمیز"], value="رسمی")


    with gr.Row():
        token_count = gr.Textbox(label="🔢 تعداد توکن‌ها", interactive=False)
        token_price = gr.Textbox(label="💰 هزینه تخمینی", interactive=False)

    with gr.Row():
        file_input = gr.File(label="📂 فایل خود را آپلود کنید", file_types=[".pdf", ".txt"])

    query_input.submit(fn=chat_with_bot, 
                        inputs=[query_input, file_input, summarize_checkbox, tone_dropdown], 
                        outputs=[chat_output, summary_output, token_count, token_price])
    
    submit_button.click(fn=chat_with_bot, 
                        inputs=[query_input, file_input, summarize_checkbox, tone_dropdown], 
                        outputs=[chat_output, summary_output, token_count, token_price])

demo.launch()