Zenkad commited on
Commit
41e7713
·
verified ·
1 Parent(s): 3c418d2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +190 -0
app.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from transformers import (
4
+ AutoTokenizer,
5
+ AutoModelForSeq2SeqLM,
6
+ AutoModelForCausalLM,
7
+ )
8
+ import pdfplumber
9
+
10
+ # ---- Modeller ----
11
+
12
+ CORE_MODEL_NAME = "TURKCELL/Turkcell-LLM-7b-v1" # Ana sohbet / QA beyni
13
+ SUMM_MODEL_NAME = "mukayese/mt5-base-turkish-summarization" # Özet beyni
14
+
15
+ device = "cuda" if torch.cuda.is_available() else "cpu"
16
+
17
+ # Özet modeli (mT5)
18
+ summ_tokenizer = AutoTokenizer.from_pretrained(SUMM_MODEL_NAME)
19
+ summ_model = AutoModelForSeq2SeqLM.from_pretrained(SUMM_MODEL_NAME).to(device)
20
+
21
+ # Ana LLM (Turkcell-LLM)
22
+ core_tokenizer = AutoTokenizer.from_pretrained(CORE_MODEL_NAME)
23
+ core_model = AutoModelForCausalLM.from_pretrained(
24
+ CORE_MODEL_NAME,
25
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
26
+ device_map="auto" if torch.cuda.is_available() else None,
27
+ )
28
+ if device == "cpu":
29
+ core_model.to(device)
30
+
31
+
32
+ # ---- Yardımcı fonksiyonlar ----
33
+
34
+ def extract_pdf_text(pdf_file) -> str:
35
+ """
36
+ Yüklenen PDF dosyasından düz metin çıkarır.
37
+ """
38
+ if pdf_file is None:
39
+ return ""
40
+
41
+ text_pages = []
42
+ with pdfplumber.open(pdf_file.name) as pdf:
43
+ for page in pdf.pages:
44
+ page_text = page.extract_text() or ""
45
+ text_pages.append(page_text)
46
+
47
+ full_text = "\n\n".join(text_pages).strip()
48
+ return full_text
49
+
50
+
51
+ def summarize_text(text: str, max_input_chars: int = 6000) -> str:
52
+ """
53
+ PDF metnini kısaltarak mT5 ile özetler.
54
+ """
55
+ if not text:
56
+ return "PDF'ten metin çıkarılamadı veya dosya boş görünüyor."
57
+
58
+ # Çok uzun metni kırp (MVP için basit truncation)
59
+ text = text[:max_input_chars]
60
+
61
+ inputs = summ_tokenizer(
62
+ text,
63
+ return_tensors="pt",
64
+ truncation=True,
65
+ max_length=1024,
66
+ ).to(device)
67
+
68
+ with torch.no_grad():
69
+ output_ids = summ_model.generate(
70
+ **inputs,
71
+ max_length=256,
72
+ num_beams=4,
73
+ early_stopping=True,
74
+ )
75
+
76
+ summary = summ_tokenizer.decode(output_ids[0], skip_special_tokens=True)
77
+ return summary.strip()
78
+
79
+
80
+ def answer_question_from_text(text: str, question: str, max_context_chars: int = 4000) -> str:
81
+ """
82
+ PDF metni + kullanıcının sorusuna göre, Turkcell-LLM ile cevap üretir.
83
+ """
84
+ if not text:
85
+ return "Önce geçerli bir PDF yüklemelisin."
86
+
87
+ if not question:
88
+ return "Lütfen PDF hakkında bir soru yaz."
89
+
90
+ # Konteksti çok büyütmemek için basit truncation
91
+ context = text[:max_context_chars]
92
+
93
+ prompt = (
94
+ "Sen ZenkaMind adında, Türkçe konuşan akıllı bir asistansın. "
95
+ "Kullanıcının verdiği belge metnine göre soruya cevap ver. "
96
+ "Bilmediğin şeyi uydurma.\n\n"
97
+ "Belge metni:\n"
98
+ f"{context}\n\n"
99
+ f"Soru: {question}\n"
100
+ "Cevap:"
101
+ )
102
+
103
+ inputs = core_tokenizer(
104
+ prompt,
105
+ return_tensors="pt",
106
+ truncation=True,
107
+ max_length=4096,
108
+ ).to(core_model.device)
109
+
110
+ with torch.no_grad():
111
+ output_ids = core_model.generate(
112
+ **inputs,
113
+ max_length=512,
114
+ do_sample=True,
115
+ top_p=0.9,
116
+ temperature=0.7,
117
+ )
118
+
119
+ full_answer = core_tokenizer.decode(output_ids[0], skip_special_tokens=True)
120
+
121
+ # Prompt'u cevaptan ayırmak için basit kesme
122
+ if "Cevap:" in full_answer:
123
+ answer = full_answer.split("Cevap:", 1)[-1].strip()
124
+ else:
125
+ answer = full_answer.strip()
126
+
127
+ return answer
128
+
129
+
130
+ # ---- Gradio Arayüzü ----
131
+
132
+ def summarize_pdf(pdf_file):
133
+ text = extract_pdf_text(pdf_file)
134
+ if not text:
135
+ return "PDF'ten metin çıkarılamadı. Dosya okunamıyor olabilir."
136
+ return summarize_text(text)
137
+
138
+
139
+ def qa_on_pdf(pdf_file, question):
140
+ text = extract_pdf_text(pdf_file)
141
+ return answer_question_from_text(text, question)
142
+
143
+
144
+ with gr.Blocks() as demo:
145
+ gr.Markdown(
146
+ """
147
+ # 🧠 ZenkaMind PDF Analiz (MVP)
148
+
149
+ - PDF yükle
150
+ - İstersen sadece özet al
151
+ - İstersen PDF hakkında soru sor
152
+ """
153
+ )
154
+
155
+ with gr.Row():
156
+ pdf_input = gr.File(label="PDF dosyası yükle", file_types=[".pdf"])
157
+
158
+ question = gr.Textbox(
159
+ label="PDF hakkında soru sor (opsiyonel)",
160
+ placeholder="Örnek: Bu PDF'in ana fikri ne?",
161
+ )
162
+
163
+ with gr.Row():
164
+ btn_summary = gr.Button("📄 PDF'yi Özetle")
165
+ btn_qa = gr.Button("❓ Soruyu Cevapla")
166
+
167
+ summary_output = gr.Textbox(
168
+ label="Özet",
169
+ lines=10,
170
+ )
171
+
172
+ answer_output = gr.Textbox(
173
+ label="Cevap",
174
+ lines=10,
175
+ )
176
+
177
+ btn_summary.click(
178
+ fn=summarize_pdf,
179
+ inputs=[pdf_input],
180
+ outputs=[summary_output],
181
+ )
182
+
183
+ btn_qa.click(
184
+ fn=qa_on_pdf,
185
+ inputs=[pdf_input, question],
186
+ outputs=[answer_output],
187
+ )
188
+
189
+ if __name__ == "__main__":
190
+ demo.launch(