First Initialization
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import re
|
||||
import numpy as np
|
||||
from sentence_transformers import SentenceTransformer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
|
||||
|
||||
class Segmenter:
|
||||
def __init__(self):
|
||||
print("Loading models :")
|
||||
|
||||
self.model_bge = SentenceTransformer("C:/Models/bge-m3", model_kwargs={"use_safetensors": False})
|
||||
self.model_e5 = SentenceTransformer("C:/Models/multilingual-e5-large")
|
||||
self.model_labse = SentenceTransformer("C:/Models/LaBSE_Local")
|
||||
self.model_parsroberta = SentenceTransformer("C:/Models/ParsRoberta")
|
||||
|
||||
print("4 models loaded successfully")
|
||||
|
||||
def get_similarities(self, text1, text2):
|
||||
"""محاسبه میانگین شباهت کسینوسی از ۴ مدل برای دو متن داده شده"""
|
||||
emb_bge = self.model_bge.encode([text1, text2])
|
||||
emb_e5 = self.model_e5.encode([text1, text2])
|
||||
emb_labse = self.model_labse.encode([text1, text2])
|
||||
emb_parsroberta = self.model_parsroberta.encode([text1, text2])
|
||||
|
||||
sim_bge = cosine_similarity([emb_bge[0]], [emb_bge[1]])[0][0]
|
||||
sim_e5 = cosine_similarity([emb_e5[0]], [emb_e5[1]])[0][0]
|
||||
sim_labse = cosine_similarity([emb_labse[0]], [emb_labse[1]])[0][0]
|
||||
sim_parsroberta = cosine_similarity([emb_parsroberta[0]], [emb_parsroberta[1]])[0][0]
|
||||
|
||||
# میانگینگیری از هر ۴ مدل
|
||||
return np.mean([sim_bge, sim_e5, sim_labse, sim_parsroberta])
|
||||
|
||||
def calculate_depth_scores(self, similarities):
|
||||
"""محاسبه عمق درهها (Gap Scores) با استفاده از قلههای چپ و راست"""
|
||||
depth_scores = []
|
||||
n = len(similarities)
|
||||
|
||||
for i in range(n):
|
||||
left_peak = similarities[i]
|
||||
for j in range(i, -1, -1):
|
||||
if similarities[j] >= left_peak:
|
||||
left_peak = similarities[j]
|
||||
else:
|
||||
break
|
||||
|
||||
right_peak = similarities[i]
|
||||
for j in range(i, n):
|
||||
if similarities[j] >= right_peak:
|
||||
right_peak = similarities[j]
|
||||
else:
|
||||
break
|
||||
|
||||
depth = (left_peak - similarities[i]) + (right_peak - similarities[i])
|
||||
depth_scores.append(depth)
|
||||
|
||||
return depth_scores
|
||||
|
||||
def extract_sentences(self, text):
|
||||
"""جداسازی متن اولیه به جملات"""
|
||||
text = text.replace('\n', ' ')
|
||||
sentences = [s.strip() for s in re.split(r'(?<=[.!?؟]) +', text) if s.strip()]
|
||||
return sentences
|
||||
|
||||
def segment_items(self, items, force_count=None, std_multiplier=0.5, min_depth=0.02):
|
||||
"""
|
||||
دریافت جملات یا واحدهای معنایی و کلاسترینگ آنها.
|
||||
اگر پارامتر force_count ارسال شود، الگوریتم موظف است دقیقاً همان تعداد سگمنت تولید کند.
|
||||
"""
|
||||
n_items = len(items)
|
||||
if n_items < 2:
|
||||
return [items]
|
||||
|
||||
similarities = []
|
||||
for i in range(n_items - 1):
|
||||
sim = self.get_similarities(items[i], items[i + 1])
|
||||
similarities.append(sim)
|
||||
|
||||
depth_scores = self.calculate_depth_scores(similarities)
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# حالت اجباری: رساندن تعداد سگمنتها به عدد دقیق (مثلا 7)
|
||||
# -------------------------------------------------------------
|
||||
if force_count and 1 < force_count < n_items:
|
||||
# پیدا کردن عمیقترین درهها برای ایجاد دقیقا force_count - 1 برش
|
||||
top_cut_indices = np.argsort(depth_scores)[-(force_count - 1):]
|
||||
top_cut_indices = sorted(top_cut_indices)
|
||||
|
||||
grouped_segments = []
|
||||
start = 0
|
||||
for idx in top_cut_indices:
|
||||
grouped_segments.append(items[start:idx + 1])
|
||||
start = idx + 1
|
||||
grouped_segments.append(items[start:])
|
||||
return grouped_segments
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# حالت عادی داینامیک: در سطوح پایینتر که هنوز به تعداد هدف نرسیدهایم
|
||||
# -------------------------------------------------------------
|
||||
mean_depth = np.mean(depth_scores)
|
||||
std_depth = np.std(depth_scores)
|
||||
cutoff_threshold = mean_depth + (std_multiplier * std_depth)
|
||||
|
||||
grouped_segments = []
|
||||
current_segment = [items[0]]
|
||||
|
||||
for i in range(len(similarities)):
|
||||
if depth_scores[i] >= cutoff_threshold and depth_scores[i] > min_depth:
|
||||
grouped_segments.append(current_segment)
|
||||
current_segment = [items[i + 1]]
|
||||
else:
|
||||
current_segment.append(items[i + 1])
|
||||
|
||||
if current_segment:
|
||||
grouped_segments.append(current_segment)
|
||||
|
||||
return grouped_segments
|
||||
Reference in New Issue
Block a user