Update app.py
Browse files
app.py
CHANGED
@@ -854,53 +854,7 @@ class PlotlyVisualizer:
|
|
854 |
height=400,
|
855 |
showlegend=False
|
856 |
)
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
return fig
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
@staticmethod
|
905 |
@handle_errors(default_return=None)
|
906 |
def create_batch_summary(results: List[Dict], theme: ThemeContext) -> go.Figure:
|
@@ -924,38 +878,12 @@ class PlotlyVisualizer:
|
|
924 |
title=f"Batch Analysis Summary ({len(results)} texts)",
|
925 |
height=400
|
926 |
)
|
927 |
-
|
928 |
return fig
|
929 |
-
|
930 |
@staticmethod
|
931 |
@handle_errors(default_return=None)
|
932 |
def create_confidence_distribution(results: List[Dict]) -> go.Figure:
|
933 |
"""Create confidence distribution plot"""
|
934 |
confidences = [r['confidence'] for r in results if 'confidence' in r and r['sentiment'] != 'Error']
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
if not confidences:
|
960 |
return go.Figure()
|
961 |
|
@@ -966,56 +894,12 @@ class PlotlyVisualizer:
|
|
966 |
opacity=0.7
|
967 |
)])
|
968 |
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
fig.update_layout(
|
1013 |
title="Confidence Distribution",
|
1014 |
xaxis_title="Confidence Score",
|
1015 |
yaxis_title="Frequency",
|
1016 |
height=400
|
1017 |
)
|
1018 |
-
|
1019 |
return fig
|
1020 |
|
1021 |
@staticmethod
|
@@ -1146,19 +1030,6 @@ class DataHandler:
|
|
1146 |
return '\n'.join(texts)
|
1147 |
|
1148 |
return content
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
class SentimentApp:
|
1163 |
"""Optimized multilingual sentiment analysis application"""
|
1164 |
|
@@ -1180,53 +1051,15 @@ class SentimentApp:
|
|
1180 |
|
1181 |
# Chinese
|
1182 |
["这部电影节奏拖沓,剧情老套,完全没有让我产生任何共鸣,是一次失望的观影体验。演员的表演也显得做作,缺乏真实感。看到最后甚至有点不耐烦,整体表现乏善可陈。"],
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
# Spanish
|
1192 |
["Una obra maestra del cine contemporáneo, con actuaciones sobresalientes, un guion bien escrito y una dirección impecable. Cada plano parecía cuidadosamente pensado, y la historia avanzaba con una intensidad emocional que mantenía al espectador cautivado. Definitivamente una película que vale la pena volver a ver."],
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
# French
|
1197 |
["Je m'attendais à beaucoup mieux. Le scénario était confus, les dialogues ennuyeux, et je me suis presque endormi au milieu du film. Même la mise en scène, habituellement un point fort, manquait cruellement d'inspiration cette fois-ci."],
|
1198 |
-
|
1199 |
-
|
1200 |
# German
|
1201 |
["Der Film war ein emotionales Erlebnis mit großartigen Bildern, einem mitreißenden Soundtrack und einer Geschichte, die zum Nachdenken anregt. Besonders beeindruckend war die schauspielerische Leistung der Hauptdarsteller, die eine tiefe Menschlichkeit vermittelten. Es ist ein Film, der lange nachwirkt."],
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
# Swedish
|
1210 |
["Filmen var en besvikelse – tråkig handling, överdrivet skådespeleri och ett slut som inte gav något avslut alls. Den kändes forcerad och saknade en tydlig röd tråd. Jag gick från biografen med en känsla av tomhet och frustration."]
|
1211 |
]
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
|
1230 |
@handle_errors(default_return=("Please enter text", None, None))
|
1231 |
def analyze_single(self, text: str, language: str, theme: str, clean_text: bool,
|
1232 |
remove_punct: bool, remove_nums: bool):
|
@@ -1287,13 +1120,6 @@ class SentimentApp:
|
|
1287 |
|
1288 |
# Parse batch input
|
1289 |
texts = TextProcessor.parse_batch_input(batch_text)
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
if len(texts) > config.BATCH_SIZE_LIMIT:
|
1298 |
return f"Too many texts. Maximum {config.BATCH_SIZE_LIMIT} allowed.", None, None, None
|
1299 |
|
@@ -1414,11 +1240,6 @@ class SentimentApp:
|
|
1414 |
|
1415 |
theme_ctx = ThemeContext(theme)
|
1416 |
|
1417 |
-
|
1418 |
-
|
1419 |
-
|
1420 |
-
|
1421 |
-
|
1422 |
with memory_cleanup():
|
1423 |
fig = PlotlyVisualizer.create_history_dashboard(history, theme_ctx)
|
1424 |
stats = self.history.get_stats()
|
@@ -1669,131 +1490,24 @@ def create_interface():
|
|
1669 |
app.plot_history,
|
1670 |
inputs=history_theme,
|
1671 |
outputs=[history_dashboard, history_status]
|
1672 |
-
|
1673 |
-
|
1674 |
-
|
1675 |
-
|
1676 |
-
|
1677 |
-
|
1678 |
-
|
1679 |
-
|
1680 |
-
|
1681 |
-
|
1682 |
-
|
1683 |
-
|
1684 |
-
|
1685 |
-
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
|
1690 |
-
|
1691 |
-
|
1692 |
-
|
1693 |
-
|
1694 |
-
|
1695 |
-
|
1696 |
-
|
1697 |
-
|
1698 |
-
|
1699 |
-
|
1700 |
-
|
1701 |
-
|
1702 |
-
|
1703 |
-
|
1704 |
-
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
1708 |
-
|
1709 |
-
|
1710 |
-
|
1711 |
-
|
1712 |
-
|
1713 |
-
|
1714 |
-
|
1715 |
-
|
1716 |
-
|
1717 |
-
|
1718 |
-
|
1719 |
-
|
1720 |
-
|
1721 |
-
|
1722 |
-
|
1723 |
-
|
1724 |
-
|
1725 |
-
|
1726 |
-
|
1727 |
-
|
1728 |
-
)
|
1729 |
-
|
1730 |
clear_history_btn.click(
|
1731 |
lambda: f"Cleared {app.history.clear()} entries",
|
1732 |
outputs=history_status
|
1733 |
-
|
1734 |
-
|
1735 |
-
|
1736 |
-
|
1737 |
-
|
1738 |
-
|
1739 |
-
|
1740 |
-
|
1741 |
-
|
1742 |
-
|
1743 |
-
|
1744 |
-
|
1745 |
-
|
1746 |
-
|
1747 |
-
|
1748 |
-
|
1749 |
-
|
1750 |
-
|
1751 |
)
|
1752 |
|
1753 |
status_btn.click(
|
1754 |
app.get_history_status,
|
1755 |
outputs=history_status
|
1756 |
-
|
1757 |
-
|
1758 |
-
|
1759 |
-
|
1760 |
-
|
1761 |
-
|
1762 |
-
|
1763 |
-
|
1764 |
-
|
1765 |
-
|
1766 |
-
|
1767 |
-
|
1768 |
-
|
1769 |
-
|
1770 |
-
|
1771 |
-
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
|
1784 |
)
|
1785 |
|
1786 |
export_csv_btn.click(
|
1787 |
lambda: app.data_handler.export_data(app.history.get_all(), 'csv'),
|
1788 |
outputs=[csv_download, history_status]
|
1789 |
-
|
1790 |
-
|
1791 |
)
|
1792 |
-
|
1793 |
export_json_btn.click(
|
1794 |
lambda: app.data_handler.export_data(app.history.get_all(), 'json'),
|
1795 |
outputs=[json_download, history_status]
|
1796 |
-
|
1797 |
)
|
1798 |
|
1799 |
return demo
|
|
|
854 |
height=400,
|
855 |
showlegend=False
|
856 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
857 |
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
858 |
@staticmethod
|
859 |
@handle_errors(default_return=None)
|
860 |
def create_batch_summary(results: List[Dict], theme: ThemeContext) -> go.Figure:
|
|
|
878 |
title=f"Batch Analysis Summary ({len(results)} texts)",
|
879 |
height=400
|
880 |
)
|
|
|
881 |
return fig
|
|
|
882 |
@staticmethod
|
883 |
@handle_errors(default_return=None)
|
884 |
def create_confidence_distribution(results: List[Dict]) -> go.Figure:
|
885 |
"""Create confidence distribution plot"""
|
886 |
confidences = [r['confidence'] for r in results if 'confidence' in r and r['sentiment'] != 'Error']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
887 |
if not confidences:
|
888 |
return go.Figure()
|
889 |
|
|
|
894 |
opacity=0.7
|
895 |
)])
|
896 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
897 |
fig.update_layout(
|
898 |
title="Confidence Distribution",
|
899 |
xaxis_title="Confidence Score",
|
900 |
yaxis_title="Frequency",
|
901 |
height=400
|
902 |
)
|
|
|
903 |
return fig
|
904 |
|
905 |
@staticmethod
|
|
|
1030 |
return '\n'.join(texts)
|
1031 |
|
1032 |
return content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1033 |
class SentimentApp:
|
1034 |
"""Optimized multilingual sentiment analysis application"""
|
1035 |
|
|
|
1051 |
|
1052 |
# Chinese
|
1053 |
["这部电影节奏拖沓,剧情老套,完全没有让我产生任何共鸣,是一次失望的观影体验。演员的表演也显得做作,缺乏真实感。看到最后甚至有点不耐烦,整体表现乏善可陈。"],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1054 |
# Spanish
|
1055 |
["Una obra maestra del cine contemporáneo, con actuaciones sobresalientes, un guion bien escrito y una dirección impecable. Cada plano parecía cuidadosamente pensado, y la historia avanzaba con una intensidad emocional que mantenía al espectador cautivado. Definitivamente una película que vale la pena volver a ver."],
|
|
|
|
|
|
|
1056 |
# French
|
1057 |
["Je m'attendais à beaucoup mieux. Le scénario était confus, les dialogues ennuyeux, et je me suis presque endormi au milieu du film. Même la mise en scène, habituellement un point fort, manquait cruellement d'inspiration cette fois-ci."],
|
|
|
|
|
1058 |
# German
|
1059 |
["Der Film war ein emotionales Erlebnis mit großartigen Bildern, einem mitreißenden Soundtrack und einer Geschichte, die zum Nachdenken anregt. Besonders beeindruckend war die schauspielerische Leistung der Hauptdarsteller, die eine tiefe Menschlichkeit vermittelten. Es ist ein Film, der lange nachwirkt."],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1060 |
# Swedish
|
1061 |
["Filmen var en besvikelse – tråkig handling, överdrivet skådespeleri och ett slut som inte gav något avslut alls. Den kändes forcerad och saknade en tydlig röd tråd. Jag gick från biografen med en känsla av tomhet och frustration."]
|
1062 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1063 |
@handle_errors(default_return=("Please enter text", None, None))
|
1064 |
def analyze_single(self, text: str, language: str, theme: str, clean_text: bool,
|
1065 |
remove_punct: bool, remove_nums: bool):
|
|
|
1120 |
|
1121 |
# Parse batch input
|
1122 |
texts = TextProcessor.parse_batch_input(batch_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1123 |
if len(texts) > config.BATCH_SIZE_LIMIT:
|
1124 |
return f"Too many texts. Maximum {config.BATCH_SIZE_LIMIT} allowed.", None, None, None
|
1125 |
|
|
|
1240 |
|
1241 |
theme_ctx = ThemeContext(theme)
|
1242 |
|
|
|
|
|
|
|
|
|
|
|
1243 |
with memory_cleanup():
|
1244 |
fig = PlotlyVisualizer.create_history_dashboard(history, theme_ctx)
|
1245 |
stats = self.history.get_stats()
|
|
|
1490 |
app.plot_history,
|
1491 |
inputs=history_theme,
|
1492 |
outputs=[history_dashboard, history_status]
|
1493 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1494 |
clear_history_btn.click(
|
1495 |
lambda: f"Cleared {app.history.clear()} entries",
|
1496 |
outputs=history_status
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1497 |
)
|
1498 |
|
1499 |
status_btn.click(
|
1500 |
app.get_history_status,
|
1501 |
outputs=history_status
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1502 |
)
|
1503 |
|
1504 |
export_csv_btn.click(
|
1505 |
lambda: app.data_handler.export_data(app.history.get_all(), 'csv'),
|
1506 |
outputs=[csv_download, history_status]
|
|
|
|
|
1507 |
)
|
|
|
1508 |
export_json_btn.click(
|
1509 |
lambda: app.data_handler.export_data(app.history.get_all(), 'json'),
|
1510 |
outputs=[json_download, history_status]
|
|
|
1511 |
)
|
1512 |
|
1513 |
return demo
|