Spaces:
Running
Running
Commit ·
d007853
1
Parent(s): 888b837
3.51
Browse files
app.py
CHANGED
|
@@ -21,10 +21,12 @@ from typing import Optional
|
|
| 21 |
from deep_translator import GoogleTranslator
|
| 22 |
from googletrans import Translator as LegacyTranslator
|
| 23 |
import torch
|
|
|
|
| 24 |
from transformers import (
|
| 25 |
pipeline,
|
| 26 |
AutoModelForSeq2SeqLM,
|
| 27 |
-
AutoTokenizer
|
|
|
|
| 28 |
)
|
| 29 |
|
| 30 |
class FallbackLLMSystem:
|
|
@@ -105,85 +107,147 @@ class FallbackLLMSystem:
|
|
| 105 |
st.warning(f"Event detection error: {str(e)}")
|
| 106 |
return "Нет", "Ошибка анализа"
|
| 107 |
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
return None
|
| 114 |
-
|
| 115 |
-
return ChatOpenAI(
|
| 116 |
-
base_url="https://api.groq.com/openai/v1",
|
| 117 |
-
model="llama-3.1-70b-versatile",
|
| 118 |
-
openai_api_key=st.secrets['groq_key'],
|
| 119 |
-
temperature=0.0
|
| 120 |
-
)
|
| 121 |
-
except Exception as e:
|
| 122 |
-
st.error(f"Error initializing Groq LLM: {str(e)}")
|
| 123 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
"""
|
| 130 |
-
# Initialize default return values
|
| 131 |
-
impact = "Неопределенный эффект"
|
| 132 |
-
reasoning = "Не удалось получить обоснование"
|
| 133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
try:
|
| 135 |
-
|
| 136 |
-
groq_llm = ensure_groq_llm()
|
| 137 |
-
working_llm = groq_llm if groq_llm is not None else llm
|
| 138 |
|
| 139 |
-
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
-
|
| 143 |
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
-
|
|
|
|
| 152 |
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
|
|
|
|
|
|
| 161 |
|
| 162 |
-
#
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
-
if "Impact:" in response_text and "Reasoning:" in response_text:
|
| 166 |
-
impact_part, reasoning_part = response_text.split("Reasoning:")
|
| 167 |
-
impact_temp = impact_part.split("Impact:")[1].strip()
|
| 168 |
-
|
| 169 |
-
# Validate impact category
|
| 170 |
-
valid_impacts = [
|
| 171 |
-
"Значительный риск убытков",
|
| 172 |
-
"Умеренный риск убытков",
|
| 173 |
-
"Незначительный риск убытков",
|
| 174 |
-
"Вероятность прибыли",
|
| 175 |
-
"Неопределенный эффект"
|
| 176 |
-
]
|
| 177 |
-
if impact_temp in valid_impacts:
|
| 178 |
-
impact = impact_temp
|
| 179 |
-
reasoning = reasoning_part.strip()
|
| 180 |
-
|
| 181 |
except Exception as e:
|
| 182 |
-
st.warning(f"
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
|
| 188 |
class TranslationSystem:
|
| 189 |
def __init__(self, batch_size=5):
|
|
@@ -567,7 +631,11 @@ def fuzzy_deduplicate(df, column, threshold=50):
|
|
| 567 |
|
| 568 |
def init_langchain_llm(model_choice):
|
| 569 |
try:
|
| 570 |
-
if model_choice == "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
if 'groq_key' not in st.secrets:
|
| 572 |
st.error("Groq API key not found in secrets. Please add it with the key 'groq_key'.")
|
| 573 |
st.stop()
|
|
@@ -590,21 +658,9 @@ def init_langchain_llm(model_choice):
|
|
| 590 |
temperature=0.0
|
| 591 |
)
|
| 592 |
|
| 593 |
-
elif model_choice == "Local-MT5":
|
| 594 |
return FallbackLLMSystem()
|
| 595 |
|
| 596 |
-
else: # Qwen API
|
| 597 |
-
if 'ali_key' not in st.secrets:
|
| 598 |
-
st.error("DashScope API key not found in secrets. Please add it with the key 'dashscope_api_key'.")
|
| 599 |
-
st.stop()
|
| 600 |
-
|
| 601 |
-
return ChatOpenAI(
|
| 602 |
-
base_url="https://dashscope.aliyuncs.com/api/v1",
|
| 603 |
-
model="qwen-max",
|
| 604 |
-
openai_api_key=st.secrets['ali_key'],
|
| 605 |
-
temperature=0.0
|
| 606 |
-
)
|
| 607 |
-
|
| 608 |
except Exception as e:
|
| 609 |
st.error(f"Error initializing the LLM: {str(e)}")
|
| 610 |
st.stop()
|
|
@@ -798,18 +854,17 @@ def create_output_file(df, uploaded_file, llm):
|
|
| 798 |
return output
|
| 799 |
def main():
|
| 800 |
with st.sidebar:
|
| 801 |
-
st.title("::: AI-анализ мониторинга новостей (v.3.
|
| 802 |
st.subheader("по материалам СКАН-ИНТЕРФАКС ")
|
| 803 |
|
| 804 |
|
| 805 |
|
| 806 |
model_choice = st.radio(
|
| 807 |
"Выберите модель для анализа:",
|
| 808 |
-
["
|
| 809 |
key="model_selector",
|
| 810 |
-
help="
|
| 811 |
)
|
| 812 |
-
|
| 813 |
st.markdown(
|
| 814 |
"""
|
| 815 |
Использованы технологии:
|
|
|
|
| 21 |
from deep_translator import GoogleTranslator
|
| 22 |
from googletrans import Translator as LegacyTranslator
|
| 23 |
import torch
|
| 24 |
+
|
| 25 |
from transformers import (
|
| 26 |
pipeline,
|
| 27 |
AutoModelForSeq2SeqLM,
|
| 28 |
+
AutoTokenizer,
|
| 29 |
+
AutoModelForCausalLM # 4 Qwen
|
| 30 |
)
|
| 31 |
|
| 32 |
class FallbackLLMSystem:
|
|
|
|
| 107 |
st.warning(f"Event detection error: {str(e)}")
|
| 108 |
return "Нет", "Ошибка анализа"
|
| 109 |
|
| 110 |
+
def ensure_groq_llm():
|
| 111 |
+
"""Initialize Groq LLM for impact estimation"""
|
| 112 |
+
try:
|
| 113 |
+
if 'groq_key' not in st.secrets:
|
| 114 |
+
st.error("Groq API key not found in secrets. Please add it with the key 'groq_key'.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
return None
|
| 116 |
+
|
| 117 |
+
return ChatOpenAI(
|
| 118 |
+
base_url="https://api.groq.com/openai/v1",
|
| 119 |
+
model="llama-3.1-70b-versatile",
|
| 120 |
+
openai_api_key=st.secrets['groq_key'],
|
| 121 |
+
temperature=0.0
|
| 122 |
+
)
|
| 123 |
+
except Exception as e:
|
| 124 |
+
st.error(f"Error initializing Groq LLM: {str(e)}")
|
| 125 |
+
return None
|
| 126 |
|
| 127 |
+
def estimate_impact(llm, news_text, entity):
|
| 128 |
+
"""
|
| 129 |
+
Estimate impact using Groq LLM regardless of the main model choice.
|
| 130 |
+
Falls back to the provided LLM if Groq initialization fails.
|
| 131 |
+
"""
|
| 132 |
+
# Initialize default return values
|
| 133 |
+
impact = "Неопределенный эффект"
|
| 134 |
+
reasoning = "Не удалось получить обоснование"
|
| 135 |
+
|
| 136 |
+
try:
|
| 137 |
+
# Always try to use Groq first
|
| 138 |
+
groq_llm = ensure_groq_llm()
|
| 139 |
+
working_llm = groq_llm if groq_llm is not None else llm
|
| 140 |
+
|
| 141 |
+
template = """
|
| 142 |
+
You are a financial analyst. Analyze this news piece about {entity} and assess its potential impact.
|
| 143 |
+
|
| 144 |
+
News: {news}
|
| 145 |
+
|
| 146 |
+
Classify the impact into one of these categories:
|
| 147 |
+
1. "Значительный риск убытков" (Significant loss risk)
|
| 148 |
+
2. "Умеренный риск убытков" (Moderate loss risk)
|
| 149 |
+
3. "Незначительный риск убытков" (Minor loss risk)
|
| 150 |
+
4. "Вероятность прибыли" (Potential profit)
|
| 151 |
+
5. "Неопределенный эффект" (Uncertain effect)
|
| 152 |
+
|
| 153 |
+
Provide a brief, fact-based reasoning for your assessment.
|
| 154 |
+
|
| 155 |
+
Format your response exactly as:
|
| 156 |
+
Impact: [category]
|
| 157 |
+
Reasoning: [explanation in 2-3 sentences]
|
| 158 |
"""
|
|
|
|
|
|
|
|
|
|
| 159 |
|
| 160 |
+
prompt = PromptTemplate(template=template, input_variables=["entity", "news"])
|
| 161 |
+
chain = prompt | working_llm
|
| 162 |
+
response = chain.invoke({"entity": entity, "news": news_text})
|
| 163 |
+
|
| 164 |
+
# Extract content from response
|
| 165 |
+
response_text = response.content if hasattr(response, 'content') else str(response)
|
| 166 |
+
|
| 167 |
+
if "Impact:" in response_text and "Reasoning:" in response_text:
|
| 168 |
+
impact_part, reasoning_part = response_text.split("Reasoning:")
|
| 169 |
+
impact_temp = impact_part.split("Impact:")[1].strip()
|
| 170 |
+
|
| 171 |
+
# Validate impact category
|
| 172 |
+
valid_impacts = [
|
| 173 |
+
"Значительный риск убытков",
|
| 174 |
+
"Умеренный риск убытков",
|
| 175 |
+
"Незначительный риск убытков",
|
| 176 |
+
"Вероятность прибыли",
|
| 177 |
+
"Неопределенный эффект"
|
| 178 |
+
]
|
| 179 |
+
if impact_temp in valid_impacts:
|
| 180 |
+
impact = impact_temp
|
| 181 |
+
reasoning = reasoning_part.strip()
|
| 182 |
+
|
| 183 |
+
except Exception as e:
|
| 184 |
+
st.warning(f"Error in impact estimation: {str(e)}")
|
| 185 |
+
|
| 186 |
+
return impact, reasoning
|
| 187 |
+
|
| 188 |
+
class QwenSystem:
|
| 189 |
+
def __init__(self):
|
| 190 |
+
"""Initialize Qwen 2.5 Coder model"""
|
| 191 |
try:
|
| 192 |
+
self.model_name = "Qwen/Qwen2.5-Coder-32B-Instruct"
|
|
|
|
|
|
|
| 193 |
|
| 194 |
+
# Initialize model with auto settings
|
| 195 |
+
self.model = AutoModelForCausalLM.from_pretrained(
|
| 196 |
+
self.model_name,
|
| 197 |
+
torch_dtype="auto",
|
| 198 |
+
device_map="auto"
|
| 199 |
+
)
|
| 200 |
+
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
|
| 201 |
|
| 202 |
+
st.success(f"Successfully initialized Qwen2.5 model")
|
| 203 |
|
| 204 |
+
except Exception as e:
|
| 205 |
+
st.error(f"Error initializing Qwen2.5: {str(e)}")
|
| 206 |
+
raise
|
| 207 |
+
|
| 208 |
+
def invoke(self, messages):
|
| 209 |
+
"""Process messages using Qwen's chat template"""
|
| 210 |
+
try:
|
| 211 |
+
# Prepare messages with system prompt
|
| 212 |
+
chat_messages = [
|
| 213 |
+
{"role": "system", "content": "You are wise financial analyst. You are a helpful assistant."}
|
| 214 |
+
]
|
| 215 |
+
chat_messages.extend(messages)
|
| 216 |
+
|
| 217 |
+
# Apply chat template
|
| 218 |
+
text = self.tokenizer.apply_chat_template(
|
| 219 |
+
chat_messages,
|
| 220 |
+
tokenize=False,
|
| 221 |
+
add_generation_prompt=True
|
| 222 |
+
)
|
| 223 |
|
| 224 |
+
# Prepare model inputs
|
| 225 |
+
model_inputs = self.tokenizer([text], return_tensors="pt").to(self.model.device)
|
| 226 |
|
| 227 |
+
# Generate response
|
| 228 |
+
generated_ids = self.model.generate(
|
| 229 |
+
**model_inputs,
|
| 230 |
+
max_new_tokens=512,
|
| 231 |
+
pad_token_id=self.tokenizer.pad_token_id,
|
| 232 |
+
eos_token_id=self.tokenizer.eos_token_id
|
| 233 |
+
)
|
| 234 |
|
| 235 |
+
# Extract new tokens
|
| 236 |
+
generated_ids = [
|
| 237 |
+
output_ids[len(input_ids):]
|
| 238 |
+
for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
| 239 |
+
]
|
| 240 |
|
| 241 |
+
# Decode response
|
| 242 |
+
response = self.tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
|
| 243 |
+
|
| 244 |
+
# Return in ChatOpenAI-compatible format
|
| 245 |
+
return type('Response', (), {'content': response})()
|
| 246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
except Exception as e:
|
| 248 |
+
st.warning(f"Qwen generation error: {str(e)}")
|
| 249 |
+
raise
|
| 250 |
+
|
|
|
|
|
|
|
| 251 |
|
| 252 |
class TranslationSystem:
|
| 253 |
def __init__(self, batch_size=5):
|
|
|
|
| 631 |
|
| 632 |
def init_langchain_llm(model_choice):
|
| 633 |
try:
|
| 634 |
+
if model_choice == "Qwen2.5-Coder":
|
| 635 |
+
st.info("Loading Qwen2.5-Coder model. только GPU!")
|
| 636 |
+
return QwenSystem()
|
| 637 |
+
|
| 638 |
+
elif model_choice == "Groq (llama-3.1-70b)":
|
| 639 |
if 'groq_key' not in st.secrets:
|
| 640 |
st.error("Groq API key not found in secrets. Please add it with the key 'groq_key'.")
|
| 641 |
st.stop()
|
|
|
|
| 658 |
temperature=0.0
|
| 659 |
)
|
| 660 |
|
| 661 |
+
elif model_choice == "Local-MT5":
|
| 662 |
return FallbackLLMSystem()
|
| 663 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
except Exception as e:
|
| 665 |
st.error(f"Error initializing the LLM: {str(e)}")
|
| 666 |
st.stop()
|
|
|
|
| 854 |
return output
|
| 855 |
def main():
|
| 856 |
with st.sidebar:
|
| 857 |
+
st.title("::: AI-анализ мониторинга новостей (v.3.51):::")
|
| 858 |
st.subheader("по материалам СКАН-ИНТЕРФАКС ")
|
| 859 |
|
| 860 |
|
| 861 |
|
| 862 |
model_choice = st.radio(
|
| 863 |
"Выберите модель для анализа:",
|
| 864 |
+
["Qwen2.5-Coder", "Groq (llama-3.1-70b)", "ChatGPT-4-mini", "Local-MT5"],
|
| 865 |
key="model_selector",
|
| 866 |
+
help="Выберите модель для анализа новостей"
|
| 867 |
)
|
|
|
|
| 868 |
st.markdown(
|
| 869 |
"""
|
| 870 |
Использованы технологии:
|