omersaidd commited on
Commit
170f47a
·
verified ·
1 Parent(s): e00c998

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +228 -0
app.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import torch
3
+ from pinecone import Pinecone
4
+ from transformers import AutoTokenizer, AutoModel
5
+ import time
6
+ import requests
7
+ import json
8
+
9
+ # Page configuration
10
+ st.set_page_config(
11
+ page_title="Hukuki Döküman Arama (Detaylı Özet)",
12
+ page_icon="⚖️",
13
+ layout="wide",
14
+ initial_sidebar_state="expanded"
15
+ )
16
+
17
+ # App title and description
18
+ st.title("⚖️ Hukuki Döküman Semantik Arama Detaylı Özet")
19
+ st.markdown("Bu uygulama, 10.000 hukuki dökümanı içeren bir veritabanında semantik arama yapmanızı sağlar.")
20
+
21
+ # Initialize Pinecone connection
22
+ @st.cache_resource
23
+ def initialize_pinecone():
24
+ pinecone_client = Pinecone(api_key="pcsk_5s8hcC_2zwJTQthP5PSWE992iXmbRx6ykNQbnEWLhj3fDuR1Cw9eKRn31i2zsRyyCxCmgW")
25
+ return pinecone_client.Index("etikos2")
26
+
27
+ # Load the model and tokenizer
28
+ @st.cache_resource
29
+ def load_model():
30
+ model_name = "intfloat/multilingual-e5-large"
31
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
32
+ model = AutoModel.from_pretrained(model_name)
33
+
34
+ # Use GPU if available
35
+ device = "cuda" if torch.cuda.is_available() else "cpu"
36
+ model = model.to(device)
37
+
38
+ return tokenizer, model, device
39
+
40
+ # Function to get query embedding
41
+ def get_query_embedding(query_text, tokenizer, model):
42
+ # Prepare text with prefix required by e5 model
43
+ prefix = "query: "
44
+ query_text = prefix + query_text
45
+
46
+ # Tokenize
47
+ inputs = tokenizer(
48
+ query_text,
49
+ padding=True,
50
+ truncation=True,
51
+ return_tensors="pt",
52
+ max_length=1024
53
+ ).to(model.device)
54
+
55
+ # Get embeddings
56
+ with torch.no_grad():
57
+ model_output = model(**inputs)
58
+
59
+ # Mean pooling
60
+ attention_mask = inputs['attention_mask']
61
+ token_embeddings = model_output[0]
62
+ input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
63
+ embeddings = torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)
64
+
65
+ # Normalize
66
+ embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
67
+
68
+ # Convert to list
69
+ embedding = embeddings[0].cpu().numpy().tolist()
70
+ return embedding
71
+
72
+ # Function to truncate text to a reasonable preview length
73
+ def get_text_preview(text, max_chars=1000):
74
+ if not text:
75
+ return "İçerik mevcut değil."
76
+
77
+ if len(text) <= max_chars:
78
+ return text
79
+
80
+ return text[:max_chars] + "..."
81
+
82
+ # Function to process query through Dify AI
83
+ def process_with_dify(query):
84
+ # Replace with your actual Dify API details
85
+ dify_api_key = "app-0UV1vRHHnChGssQ2Kc5UK9gg" # Replace with your actual API key
86
+ dify_api_endpoint = "https://api.dify.ai/v1/chat-messages" # Replace with your actual endpoint
87
+
88
+ headers = {
89
+ "Authorization": f"Bearer {dify_api_key}",
90
+ "Content-Type": "application/json"
91
+ }
92
+
93
+ payload = {
94
+ "inputs": {},
95
+ "query": f"{query}",
96
+ "response_mode": "blocking",
97
+ "user": "user"
98
+ }
99
+
100
+ try:
101
+ response = requests.post(dify_api_endpoint, headers=headers, json=payload)
102
+ if response.status_code == 200:
103
+ data = response.json()
104
+ return data.get("answer", "")
105
+ else:
106
+ st.warning(f"Dify AI ile iletişim kurulurken hata oluştu: {response.status_code}")
107
+ return ""
108
+ except Exception as e:
109
+ st.warning(f"Dify AI işlemi sırasında hata: {str(e)}")
110
+ return ""
111
+
112
+ # Sidebar configuration
113
+ st.sidebar.header("Arama Ayarları")
114
+ top_k = st.sidebar.slider("Gösterilecek sonuç sayısı:", 1, 30, 5)
115
+ preview_length = st.sidebar.slider("Ön izleme uzunluğu (karakter):", 500, 3000, 1000)
116
+
117
+ # Initialize resources with status indicators
118
+ with st.sidebar:
119
+ st.subheader("Sistem Durumu")
120
+
121
+ with st.status("Pinecone bağlantısı kuruluyor...", expanded=True) as status:
122
+ try:
123
+ index = initialize_pinecone()
124
+ status.update(label="Pinecone bağlantısı kuruldu ✅", state="complete", expanded=False)
125
+ except Exception as e:
126
+ status.update(label=f"Pinecone bağlantı hatası ❌: {str(e)}", state="error", expanded=True)
127
+ st.error("Veritabanına bağlanılamadı. Lütfen daha sonra tekrar deneyin.")
128
+ st.stop()
129
+
130
+ with st.status("Model yükleniyor...", expanded=True) as status:
131
+ try:
132
+ tokenizer, model, device = load_model()
133
+ status.update(label=f"Model yüklendi ✅ ({device.upper()} kullanılıyor)", state="complete", expanded=False)
134
+ except Exception as e:
135
+ status.update(label=f"Model yükleme hatası ❌: {str(e)}", state="error", expanded=True)
136
+ st.error("Model yüklenemedi. Lütfen daha sonra tekrar deneyin.")
137
+ st.stop()
138
+
139
+ # Main search interface
140
+ query = st.text_area("Aramak istediğiniz konuyu yazın:", height=100,
141
+ placeholder="Örnek: Mülkiyet hakkı ile ilgili davalar")
142
+
143
+ # Search button
144
+ search_button = st.button("🔍 Ara", type="primary", use_container_width=True)
145
+
146
+ # Execute search when button is clicked
147
+ if search_button and query:
148
+ # Process with Dify AI
149
+ with st.spinner("Sorgunuz Dify AI ile analiz ediliyor..."):
150
+ dify_output = process_with_dify(query)
151
+
152
+ if not dify_output:
153
+ st.error("Dify AI'dan yanıt alınamadı. Lütfen tekrar deneyin.")
154
+ st.stop()
155
+
156
+ # Show the query transformation
157
+ with st.expander("Sorgu Dönüşümü", expanded=True):
158
+ st.write("Orijinal sorgu:")
159
+ st.info(query)
160
+ st.write("Dify AI çıktısı (arama için kullanılacak):")
161
+ st.success(dify_output)
162
+
163
+ # Perform the search with ONLY the Dify AI output
164
+ with st.spinner("Arama yapılıyor..."):
165
+ try:
166
+ # Get query embedding from Dify AI output
167
+ start_time = time.time()
168
+ query_embedding = get_query_embedding(dify_output, tokenizer, model)
169
+
170
+ # Search Pinecone
171
+ search_results = index.query(
172
+ vector=query_embedding,
173
+ top_k=top_k,
174
+ include_metadata=True
175
+ )
176
+
177
+ elapsed_time = time.time() - start_time
178
+
179
+ # Display results
180
+ st.success(f"Arama tamamlandı! ({elapsed_time:.2f} saniye)")
181
+
182
+ if not search_results.matches:
183
+ st.info("Aramanıza uygun sonuç bulunamadı.")
184
+ else:
185
+ st.subheader(f"Arama Sonuçları ({len(search_results.matches)} döküman)")
186
+
187
+ # Display each result in a card
188
+ for i, match in enumerate(search_results.matches):
189
+ with st.container():
190
+ col1, col2 = st.columns([4, 1])
191
+
192
+ with col1:
193
+ st.markdown(f"### {i+1}. {match.metadata.get('daire', 'Bilinmeyen Daire')}")
194
+
195
+ with col2:
196
+ st.metric(label="Benzerlik", value=f"{match.score*100:.1f}%")
197
+
198
+ st.markdown("**Döküman Bilgileri:**")
199
+ st.markdown(f"""
200
+ - **Karar No:** {match.metadata.get('karar_no', 'Belirtilmemiş')}
201
+ - **Esas No:** {match.metadata.get('esas_no', 'Belirtilmemiş')}
202
+ - **Tarih:** {match.metadata.get('tarih', 'Belirtilmemiş')}
203
+ """)
204
+
205
+ # Get full text content from metadata
206
+ text_content = match.metadata.get('text', match.metadata.get('text_snippet', ''))
207
+
208
+ # Display text content in an expandable section
209
+ with st.expander("Döküman İçeriği", expanded=True):
210
+ st.markdown(get_text_preview(text_content, preview_length))
211
+
212
+ # Add download button if text content exists
213
+ if text_content:
214
+ st.download_button(
215
+ label="Tam Metni İndir",
216
+ data=text_content,
217
+ file_name=f"karar_{match.metadata.get('karar_no', 'bilinmeyen')}.txt",
218
+ mime="text/plain"
219
+ )
220
+
221
+ st.divider()
222
+
223
+ except Exception as e:
224
+ st.error(f"Arama sırasında bir hata oluştu: {str(e)}")
225
+
226
+ # Footer
227
+ st.sidebar.markdown("---")
228
+ st.sidebar.caption("©2025 Etikos AI")