Spaces:
Running
Running
Commit
·
3cdf7eb
1
Parent(s):
ab0d1cf
3.70
Browse files
app.py
CHANGED
@@ -478,7 +478,8 @@ class ProcessingUI:
|
|
478 |
unsafe_allow_html=True
|
479 |
)
|
480 |
self.progress_bar = st.progress(0)
|
481 |
-
|
|
|
482 |
# Create tabs for different views
|
483 |
tab1, tab2, tab3, tab4 = st.tabs([
|
484 |
"📊 Основные метрики",
|
@@ -684,7 +685,7 @@ class ProcessingUI:
|
|
684 |
stats = st.session_state.processing_stats
|
685 |
|
686 |
# Processing speed chart
|
687 |
-
speeds = stats['processing_speed'][-
|
688 |
fig_speed = go.Figure(data=go.Scatter(y=speeds, mode='lines'))
|
689 |
fig_speed.update_layout(title='Processing Speed Over Time')
|
690 |
self.speed_chart.plotly_chart(fig_speed, use_container_width=True)
|
@@ -695,6 +696,7 @@ class ProcessingUI:
|
|
695 |
"""Update progress bar and elapsed time"""
|
696 |
progress = current / total
|
697 |
self.progress_bar.progress(progress)
|
|
|
698 |
|
699 |
# Update elapsed time
|
700 |
elapsed = time.time() - st.session_state.processing_stats['start_time']
|
@@ -969,14 +971,15 @@ def process_file(uploaded_file, model_choice, translation_method=None):
|
|
969 |
|
970 |
|
971 |
# Show events in real-time
|
972 |
-
if event_type != "Нет":
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
|
979 |
#Calculate processing speed (items per second)
|
|
|
980 |
time_delta = current_time - last_update_time
|
981 |
if time_delta > 0:
|
982 |
processing_speed = 1 / time_delta # items per second
|
@@ -988,29 +991,34 @@ def process_file(uploaded_file, model_choice, translation_method=None):
|
|
988 |
|
989 |
|
990 |
# Handle negative sentiment
|
|
|
991 |
if sentiment == "Negative":
|
992 |
try:
|
|
|
|
|
|
|
|
|
993 |
impact, reasoning = estimate_impact(
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
)
|
|
|
998 |
except Exception as e:
|
999 |
impact = "Неопределенный эффект"
|
1000 |
reasoning = "Error in impact estimation"
|
1001 |
-
|
1002 |
-
st.warning("Лимит запросов исчерпался. Иду на fallback.")
|
1003 |
|
1004 |
df.at[idx, 'Impact'] = impact
|
1005 |
df.at[idx, 'Reasoning'] = reasoning
|
1006 |
|
1007 |
# Show negative alert in real-time
|
1008 |
-
ui.show_negative(
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
)
|
1014 |
|
1015 |
processed_rows_df = pd.concat([processed_rows_df, df.iloc[[idx]]], ignore_index=True)
|
1016 |
|
@@ -1186,41 +1194,85 @@ def init_langchain_llm(model_choice):
|
|
1186 |
|
1187 |
|
1188 |
def estimate_impact(llm, news_text, entity):
|
1189 |
-
template = """
|
1190 |
-
Analyze the following news piece about the entity "{entity}" and estimate its monetary impact in Russian rubles for this entity in the next 6 months.
|
1191 |
-
|
1192 |
-
If precise monetary estimate is not possible, categorize the impact as one of the following:
|
1193 |
-
1. "Значительный риск убытков"
|
1194 |
-
2. "Умеренный риск убытков"
|
1195 |
-
3. "Незначительный риск убытков"
|
1196 |
-
4. "Вероятность прибыли"
|
1197 |
-
5. "Неопределенный эффект"
|
1198 |
-
|
1199 |
-
Provide brief reasoning (maximum 100 words).
|
1200 |
-
|
1201 |
-
News: {news}
|
1202 |
-
|
1203 |
-
Your response should be in the following format:
|
1204 |
-
Impact: [Your estimate or category]
|
1205 |
-
Reasoning: [Your reasoning]
|
1206 |
"""
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
impact = "Неопределенный эффект"
|
1212 |
reasoning = "Не удалось получить обоснование"
|
1213 |
|
1214 |
-
# Extract content from response
|
1215 |
-
response_text = response.content if hasattr(response, 'content') else str(response)
|
1216 |
-
|
1217 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1218 |
if "Impact:" in response_text and "Reasoning:" in response_text:
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1222 |
except Exception as e:
|
1223 |
-
st.
|
|
|
|
|
1224 |
|
1225 |
return impact, reasoning
|
1226 |
|
@@ -1412,7 +1464,7 @@ def main():
|
|
1412 |
st.set_page_config(layout="wide")
|
1413 |
|
1414 |
with st.sidebar:
|
1415 |
-
st.title("::: AI-анализ мониторинга новостей (v.3.
|
1416 |
st.subheader("по материалам СКАН-ИНТЕРФАКС")
|
1417 |
|
1418 |
model_choice = st.radio(
|
|
|
478 |
unsafe_allow_html=True
|
479 |
)
|
480 |
self.progress_bar = st.progress(0)
|
481 |
+
self.status = st.empty()
|
482 |
+
|
483 |
# Create tabs for different views
|
484 |
tab1, tab2, tab3, tab4 = st.tabs([
|
485 |
"📊 Основные метрики",
|
|
|
685 |
stats = st.session_state.processing_stats
|
686 |
|
687 |
# Processing speed chart
|
688 |
+
speeds = stats['processing_speed'][-1:] # Last 1 measurement
|
689 |
fig_speed = go.Figure(data=go.Scatter(y=speeds, mode='lines'))
|
690 |
fig_speed.update_layout(title='Processing Speed Over Time')
|
691 |
self.speed_chart.plotly_chart(fig_speed, use_container_width=True)
|
|
|
696 |
"""Update progress bar and elapsed time"""
|
697 |
progress = current / total
|
698 |
self.progress_bar.progress(progress)
|
699 |
+
self.status.text(f"Обрабатываем {current} из {total} сообщений...")
|
700 |
|
701 |
# Update elapsed time
|
702 |
elapsed = time.time() - st.session_state.processing_stats['start_time']
|
|
|
971 |
|
972 |
|
973 |
# Show events in real-time
|
974 |
+
#if event_type != "Нет":
|
975 |
+
# ui.show_event(
|
976 |
+
# row['Объект'],
|
977 |
+
# event_type,
|
978 |
+
# row['Заголовок']
|
979 |
+
# )
|
980 |
|
981 |
#Calculate processing speed (items per second)
|
982 |
+
current_time = time.time()
|
983 |
time_delta = current_time - last_update_time
|
984 |
if time_delta > 0:
|
985 |
processing_speed = 1 / time_delta # items per second
|
|
|
991 |
|
992 |
|
993 |
# Handle negative sentiment
|
994 |
+
|
995 |
if sentiment == "Negative":
|
996 |
try:
|
997 |
+
# Initialize Groq LLM if not already done
|
998 |
+
if 'groq_llm' not in locals():
|
999 |
+
groq_llm = ensure_groq_llm()
|
1000 |
+
|
1001 |
impact, reasoning = estimate_impact(
|
1002 |
+
groq_llm if groq_llm is not None else llm,
|
1003 |
+
translated_text,
|
1004 |
+
row['Объект']
|
1005 |
)
|
1006 |
+
|
1007 |
except Exception as e:
|
1008 |
impact = "Неопределенный эффект"
|
1009 |
reasoning = "Error in impact estimation"
|
1010 |
+
st.warning(f"Impact estimation error: {str(e)}")
|
|
|
1011 |
|
1012 |
df.at[idx, 'Impact'] = impact
|
1013 |
df.at[idx, 'Reasoning'] = reasoning
|
1014 |
|
1015 |
# Show negative alert in real-time
|
1016 |
+
#ui.show_negative(
|
1017 |
+
# row['Объект'],
|
1018 |
+
# row['Заголовок'],
|
1019 |
+
# reasoning,
|
1020 |
+
# impact
|
1021 |
+
#)
|
1022 |
|
1023 |
processed_rows_df = pd.concat([processed_rows_df, df.iloc[[idx]]], ignore_index=True)
|
1024 |
|
|
|
1194 |
|
1195 |
|
1196 |
def estimate_impact(llm, news_text, entity):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1197 |
"""
|
1198 |
+
Estimate impact using Groq LLM regardless of the main model choice.
|
1199 |
+
Falls back to the provided LLM if Groq initialization fails.
|
1200 |
+
"""
|
1201 |
+
# Initialize default return values
|
1202 |
impact = "Неопределенный эффект"
|
1203 |
reasoning = "Не удалось получить обоснование"
|
1204 |
|
|
|
|
|
|
|
1205 |
try:
|
1206 |
+
# Always try to use Groq first
|
1207 |
+
groq_llm = ensure_groq_llm()
|
1208 |
+
working_llm = groq_llm if groq_llm is not None else llm
|
1209 |
+
|
1210 |
+
template = """
|
1211 |
+
You are a financial analyst. Analyze this news piece about {entity} and assess its potential impact.
|
1212 |
+
|
1213 |
+
News: {news}
|
1214 |
+
|
1215 |
+
Classify the impact into one of these categories:
|
1216 |
+
1. "Значительный риск убытков" (Significant loss risk)
|
1217 |
+
2. "Умеренный риск убытков" (Moderate loss risk)
|
1218 |
+
3. "Незначительный риск убытков" (Minor loss risk)
|
1219 |
+
4. "Вероятность прибыли" (Potential profit)
|
1220 |
+
5. "Неопределенный эффект" (Uncertain effect)
|
1221 |
+
|
1222 |
+
Provide a brief, fact-based reasoning for your assessment.
|
1223 |
+
|
1224 |
+
Format your response exactly as:
|
1225 |
+
Impact: [category]
|
1226 |
+
Reasoning: [explanation in 2-3 sentences]
|
1227 |
+
"""
|
1228 |
+
|
1229 |
+
prompt = PromptTemplate(template=template, input_variables=["entity", "news"])
|
1230 |
+
chain = prompt | working_llm
|
1231 |
+
|
1232 |
+
# Handle both dictionary and direct string inputs
|
1233 |
+
if isinstance(news_text, dict):
|
1234 |
+
response = chain.invoke(news_text)
|
1235 |
+
else:
|
1236 |
+
response = chain.invoke({"entity": entity, "news": news_text})
|
1237 |
+
|
1238 |
+
# Extract content from response
|
1239 |
+
response_text = response.content if hasattr(response, 'content') else str(response)
|
1240 |
+
|
1241 |
if "Impact:" in response_text and "Reasoning:" in response_text:
|
1242 |
+
try:
|
1243 |
+
impact_part, reasoning_part = response_text.split("Reasoning:")
|
1244 |
+
impact_temp = impact_part.split("Impact:")[1].strip()
|
1245 |
+
|
1246 |
+
# Validate impact category
|
1247 |
+
valid_impacts = [
|
1248 |
+
"Значительный риск убытков",
|
1249 |
+
"Умеренный риск убытков",
|
1250 |
+
"Незначительный риск убытков",
|
1251 |
+
"Вероятность прибыли",
|
1252 |
+
"Неопределенный эффект"
|
1253 |
+
]
|
1254 |
+
|
1255 |
+
# Use fuzzy matching to handle slight variations
|
1256 |
+
best_match = None
|
1257 |
+
best_score = 0
|
1258 |
+
impact_temp_lower = impact_temp.lower()
|
1259 |
+
|
1260 |
+
for valid_impact in valid_impacts:
|
1261 |
+
score = fuzz.ratio(impact_temp_lower, valid_impact.lower())
|
1262 |
+
if score > best_score and score > 80: # 80% similarity threshold
|
1263 |
+
best_score = score
|
1264 |
+
best_match = valid_impact
|
1265 |
+
|
1266 |
+
impact = best_match if best_match else "Неопределенный эффект"
|
1267 |
+
reasoning = reasoning_part.strip()
|
1268 |
+
|
1269 |
+
except Exception as e:
|
1270 |
+
st.warning(f"Error parsing impact response: {str(e)}")
|
1271 |
+
|
1272 |
except Exception as e:
|
1273 |
+
st.warning(f"Error in impact estimation: {str(e)}")
|
1274 |
+
if 'rate limit' in str(e).lower():
|
1275 |
+
st.warning("Rate limit reached. Using fallback model.")
|
1276 |
|
1277 |
return impact, reasoning
|
1278 |
|
|
|
1464 |
st.set_page_config(layout="wide")
|
1465 |
|
1466 |
with st.sidebar:
|
1467 |
+
st.title("::: AI-анализ мониторинга новостей (v.3.70):::")
|
1468 |
st.subheader("по материалам СКАН-ИНТЕРФАКС")
|
1469 |
|
1470 |
model_choice = st.radio(
|