| import pandas as pd |
| import re |
| import numpy as np |
| import json |
| from typing import Dict, List, Any, Tuple |
| import gradio as gr |
| from pathlib import Path |
| import plotly.graph_objects as go |
| import plotly.express as px |
| from dataclasses import dataclass |
| from datetime import datetime |
|
|
| @dataclass |
| class BenchmarkMetrics: |
| """کلاس متریکهای بنچمارک""" |
| model_name: str |
| total_texts: int |
| total_entities: int |
| accuracy: float |
| recall: float |
| precision: float |
|
|
| class AnonymizationBenchmark: |
| """کلاس اصلی بنچمارک ناشناسسازی""" |
| |
| def __init__(self): |
| self.models_data = {} |
| self.benchmark_results = {} |
| |
| def load_csv_files(self, chatgpt_file, grok_file, llama_file): |
| """بارگذاری فایلهای CSV""" |
| try: |
| |
| chatgpt_df = pd.read_csv(chatgpt_file) |
| grok_df = pd.read_csv(grok_file) |
| llama_df = pd.read_csv(llama_file) |
| |
| |
| required_columns = ['original_text', 'anonymized_text'] |
| |
| for df_name, df in [('ChatGPT', chatgpt_df), ('Grok', grok_df), ('Llama', llama_df)]: |
| if not all(col in df.columns for col in required_columns): |
| raise ValueError(f"فایل {df_name} فاقد ستونهای مورد نیاز است") |
| |
| self.models_data = { |
| 'ChatGPT': chatgpt_df, |
| 'Grok': grok_df, |
| 'Llama-3.1-8B': llama_df |
| } |
| |
| return True, "فایلها با موفقیت بارگذاری شدند" |
| |
| except Exception as e: |
| return False, f"خطا در بارگذاری فایلها: {str(e)}" |
| |
| def extract_entities_from_text(self, text: str) -> Dict[str, List[str]]: |
| """استخراج موجودیتها از متن""" |
| entities = { |
| 'companies': re.findall(r'company-(\d+)', text), |
| 'persons': re.findall(r'person-(\d+)', text), |
| 'amounts': re.findall(r'amount-(\d+)', text), |
| 'percents': re.findall(r'percent-(\d+)', text), |
| 'groups': re.findall(r'group-(\d+)', text) |
| } |
| return entities |
| |
| def count_original_entities(self, text: str) -> int: |
| """تخمین تعداد موجودیتهای قابل ناشناسسازی در متن اصلی""" |
| |
| patterns = [ |
| r'[۰-۹]+(?:\.[۰-۹]+)?\s*(?:میلیارد|میلیون|هزار)?\s*(?:تومان|ریال|دلار|یورو)', |
| r'[۰-۹]+(?:\.[۰-۹]+)?\s*درصد', |
| r'\b[آ-ی\s]{2,30}\b(?:\s*(?:شرکت|بانک|گروه|سازمان))', |
| r'\b[آ-ی\s]{2,20}\b(?:\s*(?:مدیرعامل|رئیس|مدیر))', |
| r'[۰-۹]+(?:\.[۰-۹]+)?(?:\s*(?:میلیون|میلیارد|هزار))?', |
| ] |
| |
| total_entities = 0 |
| for pattern in patterns: |
| matches = re.findall(pattern, text) |
| total_entities += len(matches) |
| |
| return max(total_entities, 1) |
| |
| def check_indexing_correctness(self, entities: Dict[str, List[str]]) -> float: |
| """بررسی درستی اندیسگذاری""" |
| total_checks = 0 |
| passed_checks = 0 |
| |
| for entity_type, indices in entities.items(): |
| if not indices: |
| continue |
| |
| total_checks += 1 |
| unique_indices = sorted([int(x) for x in set(indices)]) |
| |
| |
| if unique_indices[0] == 1: |
| passed_checks += 0.5 |
| |
| |
| expected = list(range(1, len(unique_indices) + 1)) |
| if unique_indices == expected: |
| passed_checks += 0.5 |
| |
| return passed_checks / total_checks if total_checks > 0 else 0.0 |
| |
| def calculate_structure_preservation(self, original_text: str, anonymized_text: str) -> float: |
| """محاسبه امتیاز حفظ ساختار""" |
| |
| important_words = [ |
| 'میلیارد', 'میلیون', 'تومان', 'ریال', 'درصد', 'سود', 'زیان', |
| 'مدیرعامل', 'شرکت', 'بانک', 'درآمد', 'سال', 'ماه' |
| ] |
| |
| score = 0.0 |
| total_checks = len(important_words) |
| |
| for word in important_words: |
| if word in original_text and word in anonymized_text: |
| score += 1.0 |
| elif word not in original_text: |
| total_checks -= 1 |
| |
| |
| original_words = len(original_text.split()) |
| anonymized_words = len(anonymized_text.split()) |
| |
| if original_words > 0: |
| word_ratio = min(anonymized_words / original_words, 1.0) |
| score += word_ratio * 2 |
| total_checks += 2 |
| |
| return score / total_checks if total_checks > 0 else 0.0 |
| |
| def calculate_accuracy(self, original_text: str, anonymized_text: str) -> float: |
| """محاسبه درستی کلی ناشناسسازی""" |
| entities = self.extract_entities_from_text(anonymized_text) |
| |
| |
| indexing_score = self.check_indexing_correctness(entities) |
| |
| |
| structure_score = self.calculate_structure_preservation(original_text, anonymized_text) |
| |
| |
| accuracy = (indexing_score * 0.6) + (structure_score * 0.4) |
| return accuracy |
| |
| def calculate_recall(self, original_text: str, anonymized_text: str) -> float: |
| """محاسبه پوشش موجودیتها (Recall)""" |
| original_entity_count = self.count_original_entities(original_text) |
| entities = self.extract_entities_from_text(anonymized_text) |
| anonymized_entity_count = sum(len(set(v)) for v in entities.values()) |
| |
| return min(anonymized_entity_count / original_entity_count, 1.0) |
| |
| def calculate_precision(self, anonymized_text: str) -> float: |
| """محاسبه دقت شناسایی (Precision)""" |
| entities = self.extract_entities_from_text(anonymized_text) |
| |
| |
| total_entities = sum(len(v) for v in entities.values()) |
| if total_entities == 0: |
| return 0.0 |
| |
| |
| correct_entities = 0 |
| for entity_type, indices in entities.items(): |
| for idx in indices: |
| if idx.isdigit() and int(idx) > 0: |
| correct_entities += 1 |
| |
| |
| unique_entities = sum(len(set(v)) for v in entities.values()) |
| consistency_bonus = unique_entities / total_entities if total_entities > 0 else 0 |
| |
| base_precision = correct_entities / total_entities if total_entities > 0 else 0 |
| return (base_precision * 0.7) + (consistency_bonus * 0.3) |
| |
| def analyze_model(self, model_name: str, df: pd.DataFrame) -> BenchmarkMetrics: |
| """تحلیل یک مدل""" |
| print(f"تحلیل مدل {model_name}...") |
| |
| total_texts = len(df) |
| |
| |
| accuracy_scores = [] |
| recall_scores = [] |
| precision_scores = [] |
| total_entities = 0 |
| |
| for _, row in df.iterrows(): |
| original = str(row['original_text']) |
| anonymized = str(row['anonymized_text']) |
| |
| |
| accuracy_scores.append(self.calculate_accuracy(original, anonymized)) |
| recall_scores.append(self.calculate_recall(original, anonymized)) |
| precision_scores.append(self.calculate_precision(anonymized)) |
| |
| |
| entities = self.extract_entities_from_text(anonymized) |
| total_entities += sum(len(set(v)) for v in entities.values()) |
| |
| return BenchmarkMetrics( |
| model_name=model_name, |
| total_texts=total_texts, |
| total_entities=total_entities, |
| accuracy=round(np.mean(accuracy_scores), 3), |
| recall=round(np.mean(recall_scores), 3), |
| precision=round(np.mean(precision_scores), 3) |
| ) |
| |
| def run_benchmark(self) -> Tuple[bool, str, str]: |
| """اجرای بنچمارک کامل""" |
| if not self.models_data: |
| return False, "ابتدا فایلها را بارگذاری کنید", "" |
| |
| try: |
| results = {} |
| |
| |
| for model_name, df in self.models_data.items(): |
| results[model_name] = self.analyze_model(model_name, df) |
| |
| self.benchmark_results = results |
| |
| |
| html_report = self.generate_html_report() |
| |
| return True, "بنچمارک با موفقیت انجام شد", html_report |
| |
| except Exception as e: |
| return False, f"خطا در اجرای بنچمارک: {str(e)}", "" |
| |
| def generate_comparison_table(self) -> str: |
| """تولید جدول مقایسه""" |
| if not self.benchmark_results: |
| return "<p>هنوز بنچمارکی انجام نشده است</p>" |
| |
| |
| table_data = [] |
| for model_name, metrics in self.benchmark_results.items(): |
| table_data.append({ |
| 'مدل': model_name, |
| 'تعداد متنها': metrics.total_texts, |
| 'کل موجودیتها': metrics.total_entities, |
| '🎯 دقت (Accuracy)': f"{metrics.accuracy:.3f}", |
| '📊 بازیابی (Recall)': f"{metrics.recall:.3f}", |
| '✅ دقت شناسایی (Precision)': f"{metrics.precision:.3f}" |
| }) |
| |
| |
| html = """ |
| <div style="overflow-x: auto; margin: 20px 0;"> |
| <table style="width: 100%; border-collapse: collapse; font-family: 'Tahoma', sans-serif;"> |
| <thead> |
| <tr style="background-color: #4CAF50; color: white;"> |
| """ |
| |
| |
| headers = list(table_data[0].keys()) |
| for header in headers: |
| html += f"<th style='border: 1px solid #ddd; padding: 12px; text-align: center;'>{header}</th>" |
| |
| html += "</tr></thead><tbody>" |
| |
| |
| for i, row in enumerate(table_data): |
| bg_color = "#f2f2f2" if i % 2 == 0 else "white" |
| html += f"<tr style='background-color: {bg_color};'>" |
| |
| for j, (key, value) in enumerate(row.items()): |
| |
| if key in ['🎯 دقت (Accuracy)', '📊 بازیابی (Recall)', '✅ دقت شناسایی (Precision)']: |
| score = float(value) |
| if score >= 0.8: |
| color = "#4CAF50" |
| elif score >= 0.6: |
| color = "#FF9800" |
| else: |
| color = "#F44336" |
| html += f"<td style='border: 1px solid #ddd; padding: 12px; text-align: center; font-weight: bold; color: {color};'>{value}</td>" |
| else: |
| html += f"<td style='border: 1px solid #ddd; padding: 12px; text-align: center;'>{value}</td>" |
| |
| html += "</tr>" |
| |
| html += "</tbody></table></div>" |
| |
| return html |
| |
| def generate_charts(self) -> str: |
| """تولید نمودارها""" |
| if not self.benchmark_results: |
| return "" |
| |
| models = list(self.benchmark_results.keys()) |
| accuracy_scores = [self.benchmark_results[model].accuracy for model in models] |
| recall_scores = [self.benchmark_results[model].recall for model in models] |
| precision_scores = [self.benchmark_results[model].precision for model in models] |
| |
| |
| chart_html = """ |
| <div style="margin: 20px 0;"> |
| <h3 style="text-align: center; color: #333;">مقایسه متریکهای عملکرد مدلها</h3> |
| <div style="display: flex; justify-content: center; gap: 40px; background-color: #f9f9f9; padding: 30px; border-radius: 15px;"> |
| """ |
| |
| colors = ['#4CAF50', '#2196F3', '#FF9800'] |
| |
| for i, model in enumerate(models): |
| accuracy = accuracy_scores[i] |
| recall = recall_scores[i] |
| precision = precision_scores[i] |
| |
| chart_html += f""" |
| <div style="text-align: center; min-width: 200px;"> |
| <h4 style="margin-bottom: 15px; color: #333;">{model}</h4> |
| |
| <div style="margin-bottom: 10px;"> |
| <div style="font-size: 12px; color: #666; margin-bottom: 5px;">Accuracy</div> |
| <div style="background-color: {colors[0]}; width: 60px; height: {accuracy*100}px; margin: 0 auto; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 10px;"> |
| {accuracy:.3f} |
| </div> |
| </div> |
| |
| <div style="margin-bottom: 10px;"> |
| <div style="font-size: 12px; color: #666; margin-bottom: 5px;">Recall</div> |
| <div style="background-color: {colors[1]}; width: 60px; height: {recall*100}px; margin: 0 auto; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 10px;"> |
| {recall:.3f} |
| </div> |
| </div> |
| |
| <div style="margin-bottom: 10px;"> |
| <div style="font-size: 12px; color: #666; margin-bottom: 5px;">Precision</div> |
| <div style="background-color: {colors[2]}; width: 60px; height: {precision*100}px; margin: 0 auto; border-radius: 3px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 10px;"> |
| {precision:.3f} |
| </div> |
| </div> |
| </div> |
| """ |
| |
| chart_html += "</div></div>" |
| |
| return chart_html |
| |
| def generate_html_report(self) -> str: |
| """تولید گزارش HTML کامل""" |
| current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
| |
| html = f""" |
| <!DOCTYPE html> |
| <html lang="fa" dir="rtl"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>گزارش بنچمارک ناشناسسازی</title> |
| <style> |
| * {{ |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| }} |
| body {{ |
| font-family: 'Tahoma', 'Arial', sans-serif; |
| line-height: 1.6; |
| color: #333; |
| background-color: #f5f5f5; |
| padding: 20px; |
| }} |
| .container {{ |
| max-width: 1400px; |
| margin: 0 auto; |
| background-color: white; |
| border-radius: 10px; |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); |
| overflow: hidden; |
| }} |
| .header {{ |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| color: white; |
| padding: 30px; |
| text-align: center; |
| }} |
| .header h1 {{ |
| font-size: 2.5em; |
| margin-bottom: 10px; |
| }} |
| .header p {{ |
| font-size: 1.2em; |
| opacity: 0.9; |
| }} |
| .content {{ |
| padding: 30px; |
| }} |
| .summary {{ |
| background-color: #e8f5e8; |
| border-right: 5px solid #4CAF50; |
| padding: 20px; |
| margin-bottom: 30px; |
| border-radius: 5px; |
| }} |
| .section {{ |
| margin-bottom: 40px; |
| }} |
| .section h2 {{ |
| color: #333; |
| border-bottom: 2px solid #4CAF50; |
| padding-bottom: 10px; |
| margin-bottom: 20px; |
| }} |
| .metrics-grid {{ |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
| gap: 20px; |
| margin-bottom: 30px; |
| }} |
| .metric-card {{ |
| background-color: #f8f9fa; |
| border: 1px solid #dee2e6; |
| border-radius: 8px; |
| padding: 20px; |
| text-align: center; |
| transition: transform 0.2s; |
| }} |
| .metric-card:hover {{ |
| transform: translateY(-5px); |
| box-shadow: 0 5px 15px rgba(0,0,0,0.1); |
| }} |
| .metric-number {{ |
| font-size: 2em; |
| font-weight: bold; |
| color: #4CAF50; |
| margin-bottom: 5px; |
| }} |
| .metric-label {{ |
| color: #666; |
| font-size: 0.9em; |
| }} |
| .footer {{ |
| background-color: #f8f9fa; |
| padding: 20px; |
| text-align: center; |
| color: #666; |
| border-top: 1px solid #dee2e6; |
| }} |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="header"> |
| <h1>🏆 گزارش بنچمارک ناشناسسازی</h1> |
| <p>مقایسه عملکرد مدلهای ChatGPT، Grok و Llama-3.1-8B</p> |
| </div> |
| |
| <div class="content"> |
| <div class="summary"> |
| <h3>📋 خلاصه نتایج</h3> |
| <p>این گزارش نتایج بنچمارک سه مدل مختلف برای ناشناسسازی متون فارسی را نشان میدهد. |
| متریکهای ارزیابی شامل درستی اندیسگذاری، ثبات استفاده از شناسهها، حفظ ساختار متن و پوشش موجودیتها میباشد.</p> |
| </div> |
| |
| <div class="section"> |
| <h2>📊 جدول مقایسه کامل</h2> |
| {self.generate_comparison_table()} |
| </div> |
| |
| <div class="section"> |
| <h2>📈 نمودار مقایسه</h2> |
| {self.generate_charts()} |
| </div> |
| |
| <div class="section"> |
| <h2>🔍 تحلیل تفصیلی</h2> |
| {self.generate_detailed_analysis()} |
| </div> |
| </div> |
| |
| <div class="footer"> |
| <p>گزارش تولید شده در تاریخ: {current_time}</p> |
| <p>ابزار بنچمارک ناشناسسازی متون فارسی</p> |
| </div> |
| </div> |
| </body> |
| </html> |
| """ |
| |
| return html |
| |
| def generate_detailed_analysis(self) -> str: |
| """تولید تحلیل تفصیلی""" |
| if not self.benchmark_results: |
| return "<p>دادهای برای تحلیل یافت نشد</p>" |
| |
| |
| best_accuracy = max(self.benchmark_results.keys(), |
| key=lambda k: self.benchmark_results[k].accuracy) |
| best_recall = max(self.benchmark_results.keys(), |
| key=lambda k: self.benchmark_results[k].recall) |
| best_precision = max(self.benchmark_results.keys(), |
| key=lambda k: self.benchmark_results[k].precision) |
| |
| |
| avg_accuracy = np.mean([m.accuracy for m in self.benchmark_results.values()]) |
| avg_recall = np.mean([m.recall for m in self.benchmark_results.values()]) |
| avg_precision = np.mean([m.precision for m in self.benchmark_results.values()]) |
| |
| analysis = f""" |
| <div class="metrics-grid"> |
| <div class="metric-card"> |
| <div class="metric-number">🎯</div> |
| <div class="metric-label">بهترین Accuracy: {best_accuracy}</div> |
| <div style="color: #4CAF50; font-weight: bold;"> |
| {self.benchmark_results[best_accuracy].accuracy:.3f} |
| </div> |
| </div> |
| <div class="metric-card"> |
| <div class="metric-number">📊</div> |
| <div class="metric-label">بهترین Recall: {best_recall}</div> |
| <div style="color: #2196F3; font-weight: bold;"> |
| {self.benchmark_results[best_recall].recall:.3f} |
| </div> |
| </div> |
| <div class="metric-card"> |
| <div class="metric-number">✅</div> |
| <div class="metric-label">بهترین Precision: {best_precision}</div> |
| <div style="color: #FF9800; font-weight: bold;"> |
| {self.benchmark_results[best_precision].precision:.3f} |
| </div> |
| </div> |
| </div> |
| |
| <div style="background-color: #e3f2fd; border: 1px solid #2196F3; border-radius: 8px; padding: 20px; margin-top: 20px;"> |
| <h4>📈 آمار کلی:</h4> |
| <ul style="margin-top: 10px; padding-right: 20px;"> |
| <li><strong>میانگین Accuracy:</strong> {avg_accuracy:.3f}</li> |
| <li><strong>میانگین Recall:</strong> {avg_recall:.3f}</li> |
| <li><strong>میانگین Precision:</strong> {avg_precision:.3f}</li> |
| </ul> |
| </div> |
| |
| <div style="background-color: #fff3cd; border: 1px solid #ffeaa7; border-radius: 8px; padding: 20px; margin-top: 20px;"> |
| <h4>💡 تفسیر نتایج:</h4> |
| <ul style="margin-top: 10px; padding-right: 20px;"> |
| <li><strong>Accuracy:</strong> دقت کلی ناشناسسازی (ترکیب اندیسگذاری صحیح و حفظ ساختار)</li> |
| <li><strong>Recall:</strong> پوشش موجودیتها (چه درصدی از موجودیتها شناسایی شدند)</li> |
| <li><strong>Precision:</strong> دقت شناسایی (چه درصدی از شناسهها صحیح هستند)</li> |
| </ul> |
| </div> |
| """ |
| |
| return analysis |
|
|
| |
| def create_benchmark_interface(): |
| """ایجاد رابط کاربری بنچمارک""" |
| benchmark = AnonymizationBenchmark() |
| |
| with gr.Blocks( |
| title="بنچمارک ناشناسسازی", |
| theme=gr.themes.Soft(), |
| css=""" |
| .gradio-container { |
| font-family: 'Tahoma', 'Arial', sans-serif !important; |
| direction: rtl; |
| max-width: 1400px; |
| margin: 0 auto; |
| } |
| .upload-box { |
| border: 2px dashed #4CAF50; |
| border-radius: 10px; |
| padding: 20px; |
| text-align: center; |
| background-color: #f8f9fa; |
| margin: 10px 0; |
| } |
| """ |
| ) as interface: |
| |
| gr.Markdown(""" |
| # 🏆 ابزار بنچمارک ناشناسسازی متون فارسی |
| ### مقایسه عملکرد مدلهای ChatGPT، Grok و Llama-3.1-8B در ناشناسسازی متون مالی/خبری |
| """) |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| gr.Markdown("### 📁 بارگذاری فایلهای CSV") |
| |
| chatgpt_file = gr.File( |
| label="📄 فایل ChatGPT", |
| file_types=[".csv"], |
| elem_classes=["upload-box"] |
| ) |
| |
| grok_file = gr.File( |
| label="📄 فایل Grok", |
| file_types=[".csv"], |
| elem_classes=["upload-box"] |
| ) |
| |
| llama_file = gr.File( |
| label="📄 فایل Llama-3.1-8B", |
| file_types=[".csv"], |
| elem_classes=["upload-box"] |
| ) |
| |
| load_btn = gr.Button( |
| "📂 بارگذاری فایلها", |
| variant="primary", |
| size="lg" |
| ) |
| |
| benchmark_btn = gr.Button( |
| "🚀 اجرای بنچمارک", |
| variant="secondary", |
| size="lg", |
| interactive=False |
| ) |
| |
| with gr.Column(scale=2): |
| status_output = gr.Markdown("وضعیت: آماده بارگذاری فایلها") |
| |
| results_html = gr.HTML( |
| label="📊 نتایج بنچمارک", |
| visible=False |
| ) |
| |
| def load_files(chatgpt, grok, llama): |
| if not all([chatgpt, grok, llama]): |
| return "❌ لطفاً هر سه فایل را انتخاب کنید", gr.Button(interactive=False), gr.HTML(visible=False) |
| |
| success, message = benchmark.load_csv_files( |
| chatgpt.name, grok.name, llama.name |
| ) |
| |
| if success: |
| return ( |
| f"✅ {message}", |
| gr.Button(interactive=True), |
| gr.HTML(visible=False) |
| ) |
| else: |
| return ( |
| f"❌ {message}", |
| gr.Button(interactive=False), |
| gr.HTML(visible=False) |
| ) |
| |
| def run_benchmark(): |
| success, message, html_report = benchmark.run_benchmark() |
| |
| if success: |
| return ( |
| f"✅ {message}", |
| gr.HTML(value=html_report, visible=True) |
| ) |
| else: |
| return ( |
| f"❌ {message}", |
| gr.HTML(visible=False) |
| ) |
| |
| |
| load_btn.click( |
| fn=load_files, |
| inputs=[chatgpt_file, grok_file, llama_file], |
| outputs=[status_output, benchmark_btn, results_html] |
| ) |
| |
| benchmark_btn.click( |
| fn=run_benchmark, |
| outputs=[status_output, results_html] |
| ) |
| |
| |
| with gr.Accordion("📖 راهنمای استفاده", open=False): |
| gr.Markdown(""" |
| ### نحوه استفاده: |
| 1. **بارگذاری فایلها:** سه فایل CSV مربوط به نتایج ناشناسسازی مدلهای مختلف را انتخاب کنید |
| 2. **بررسی فرمت:** هر فایل باید دارای ستونهای `original_text` و `anonymized_text` باشد |
| 3. **اجرای بنچمارک:** روی دکمه "اجرای بنچمارک" کلیک کنید |
| 4. **مشاهده نتایج:** گزارش HTML کامل با جداول و نمودارها نمایش داده میشود |
| |
| ### متریکهای ارزیابی: |
| - **درستی اندیسگذاری:** بررسی شروع از 01 و پیوستگی شمارهها |
| - **ثبات شناسهها:** استفاده مداوم از یک شناسه برای یک موجودیت |
| - **حفظ ساختار:** حفظ واژگان مهم و ساختار جمله |
| - **پوشش موجودیتها:** درصد موجودیتهای شناسایی و ناشناس شده |
| - **امتیاز کلی:** ترکیب وزنی همه متریکها |
| """) |
| |
| return interface |
|
|
| |
| if __name__ == "__main__": |
| interface = create_benchmark_interface() |
| interface.launch() |