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 |
Использованы технологии:
|