Spaces:
Sleeping
Sleeping
Pablo A. Sampaio
commited on
Commit
•
627753f
1
Parent(s):
098d302
Now, it can retrieve the matches from yesterday, today or tomorrow.
Browse files- 2024-05-15-complete.txt +64 -0
- app.py +76 -26
- match_info_crawler.py +150 -0
2024-05-15-complete.txt
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
The Strongest 4 x 0 Huachipato - Copa Libertadores - finished
|
3 |
+
Deportivo Táchira 0 x 1 Nacional - Copa Libertadores - finished
|
4 |
+
Alianza Lima 1 x 1 Colo-Colo - Copa Libertadores - finished
|
5 |
+
Flamengo 4 x 0 Bolívar - Copa Libertadores - finished
|
6 |
+
Palmeiras 2 x 1 Independiente del Valle - Copa Libertadores - finished
|
7 |
+
Belgrano 1 x 0 Real Tomayapo - Copa Sul-Americana - finished
|
8 |
+
Athletico-PR 1 x 2 Danúbio - Copa Sul-Americana - finished
|
9 |
+
Lanús 5 x 0 Metropolitanos - Copa Sul-Americana - finished
|
10 |
+
Boca Juniors 1 x 1 Fortaleza - Copa Sul-Americana - finished
|
11 |
+
Cuiabá 1 x 1 Deportivo Garcilaso - Copa Sul-Americana - finished
|
12 |
+
César Vallejo 2 x 2 Always Ready - Copa Sul-Americana - finished
|
13 |
+
Ituano 1 x 0 Sport - Campeonato Brasileiro - Série B - finished
|
14 |
+
América-MG 0 x 0 Mirassol - Campeonato Brasileiro - Série B - finished
|
15 |
+
Brusque 0 x 0 Operário-PR - Campeonato Brasileiro - Série B - finished
|
16 |
+
Ponte Preta 1 x 2 Santos - Campeonato Brasileiro - Série B - finished
|
17 |
+
Paysandu 1 x 1 Goiás - Campeonato Brasileiro - Série B - finished
|
18 |
+
Ceará 2 x 1 Amazonas - Campeonato Brasileiro - Série B - finished
|
19 |
+
Porto Velho 1 x 2 Vilhena - Campeonato Rondoniense - finished
|
20 |
+
Real Noroeste 2 x 3 Rio Branco-ES - Copa Espírito Santo - finished
|
21 |
+
Sevilla 0 x 1 Cádiz - Campeonato Espanhol - finished
|
22 |
+
Rayo Vallecano 2 x 1 Granada CF - Campeonato Espanhol - finished
|
23 |
+
Celta de Vigo 2 x 1 Athletic Bilbao - Campeonato Espanhol - finished
|
24 |
+
Getafe 0 x 3 Atlético Madrid - Campeonato Espanhol - finished
|
25 |
+
Brighton 1 x 2 Chelsea - Campeonato Inglês - finished
|
26 |
+
Manchester United 3 x 2 Newcastle - Campeonato Inglês - finished
|
27 |
+
Nice 1 x 2 PSG - Campeonato Francês - finished
|
28 |
+
Reims 1 x 0 Olympique Marseille - Campeonato Francês - finished
|
29 |
+
Sudão 2 x 1 Tanzânia - Amistosos de Seleções - finished
|
30 |
+
Trindade e Tobago 2 x 0 Guiana - Amistosos de Seleções - finished
|
31 |
+
Guadalajara 0 x 0 América-MEX - Campeonato Mexicano - finished
|
32 |
+
Atalanta 0 x 1 Juventus - Copa da Itália - finished
|
33 |
+
Cincinnati 1 x 0 Atlanta United - Major League Soccer - finished
|
34 |
+
DC United 1 x 4 New York RB - Major League Soccer - finished
|
35 |
+
Montreal Impact 1 x 3 Columbus Crew - Major League Soccer - finished
|
36 |
+
Orlando City 0 x 0 Inter Miami - Major League Soccer - finished
|
37 |
+
Philadelphia Union 1 x 2 New York City - Major League Soccer - finished
|
38 |
+
Austin 1 x 0 Houston Dynamo - Major League Soccer - finished
|
39 |
+
Chicago Fire 0 x 1 Charlotte - Major League Soccer - finished
|
40 |
+
Minnesota United 2 x 2 Los Angeles Galaxy - Major League Soccer - finished
|
41 |
+
Nashville SC 2 x 0 Toronto FC - Major League Soccer - finished
|
42 |
+
Saint Louis City 0 x 2 Los Angeles FC - Major League Soccer - finished
|
43 |
+
Colorado Rapids 1 x 0 Vancouver Whitecaps - Major League Soccer - finished
|
44 |
+
Real Salt Lake 2 x 0 Seattle Sounders - Major League Soccer - finished
|
45 |
+
Portland Timbers 4 x 2 San Jose Earthquakes - Major League Soccer - finished
|
46 |
+
Shanghai Shenhua 2 x 0 Qingdao Jonoon - Campeonato Chinês - finished
|
47 |
+
Consadole Sapporo 1 x 0 Júbilo Iwata - Campeonato Japonês - finished
|
48 |
+
Kashiwa Reysol 2 x 1 Shonan Bellmare - Campeonato Japonês - finished
|
49 |
+
Tokyo Verdy 0 x 0 Gamba Osaka - Campeonato Japonês - finished
|
50 |
+
Machida Zelvia 2 x 1 Cerezo Osaka - Campeonato Japonês - finished
|
51 |
+
Albirex Niigata 3 x 1 Yokohama F. Marinos - Campeonato Japonês - finished
|
52 |
+
Nagoya Grampus 3 x 1 Tokyo - Campeonato Japonês - finished
|
53 |
+
Vissel Kobe 1 x 0 Avispa Fukuoka - Campeonato Japonês - finished
|
54 |
+
Sanfrecce Hiroshima 1 x 3 Kashima Antlers - Campeonato Japonês - finished
|
55 |
+
Sagan Tosu 5 x 2 Kawasaki Frontale - Campeonato Japonês - finished
|
56 |
+
Urawa Reds 3 x 0 Kyoto Sanga - Campeonato Japonês - finished
|
57 |
+
Gimnasia Mendoza 0 x 1 Atletico Mitre - Copa Argentina - finished
|
58 |
+
Almirante Brown 3 x 2 San Martín Tucumán - Copa Argentina - finished
|
59 |
+
Elfsborg 6 x 1 AIK - Campeonato Sueco - finished
|
60 |
+
Halmstad 3 x 0 Häcken - Campeonato Sueco - finished
|
61 |
+
Mjällby 3 x 0 Hammarby - Campeonato Sueco - finished
|
62 |
+
Västerås SK 0 x 2 Värnamo - Campeonato Sueco - finished
|
63 |
+
Gwangju 2 x 1 Ulsan - Campeonato Sul-Coreano - K-League - finished
|
64 |
+
Ipojuca Sub-20 x Atlético Torres Sub-20 - Campeonato Pernambucano - Sub-20 - not started
|
app.py
CHANGED
@@ -4,6 +4,8 @@ import gradio as gr
|
|
4 |
from openai import OpenAI
|
5 |
import google.generativeai as genai
|
6 |
|
|
|
|
|
7 |
|
8 |
LOAD_KEYS_FROM_FILES = False
|
9 |
USE_LOCAL_ASR_PIPELINE = False
|
@@ -27,8 +29,8 @@ else:
|
|
27 |
GOOGLE_API_KEY = "" if 'GOOGLE_API_KEY' not in os.environ else os.environ['GOOGLE_API_KEY']
|
28 |
assert 'HUGGINGFACE_API_KEY' in os.environ, "Hugging Face API key not found in environment variables"
|
29 |
|
30 |
-
|
31 |
-
|
32 |
|
33 |
OPENAI_CLIENT = None
|
34 |
if OPENAI_API_KEY != "":
|
@@ -45,16 +47,17 @@ AUDIO_OUT_FILE_PREFIX = "output" # prefixo do nome do arquivo de áudio .wav
|
|
45 |
|
46 |
TEMPLATE_SYSTEM_MESSAGE = """Você é assistente virtual com a função é entreter uma criança de idade entre 6 e 8 anos que adora futebol. Diretrizes para a conversa:
|
47 |
- Você é {GENRE}, seu nome é {NAME}.
|
48 |
-
- Pergunte o nome da criança.
|
49 |
-
- Fale sobre futebol, times, jogadores, seleções e grandes jogos.
|
50 |
-
- Em especial, foque no futebol do Brasil, Inglaterra e Espanha.
|
51 |
- {PERSONALITY}
|
|
|
|
|
|
|
|
|
52 |
- Fale, no máximo, três frases por mensagem.
|
53 |
"""
|
54 |
|
55 |
# Mapeia a personalidade no template e na temperatura
|
56 |
PERSONALITIES = {
|
57 |
-
"nova": ("Sua personalidade é bastante amigável e alegre,
|
58 |
"echo": ("Sua personalidade é amigável, mas objetivo. Tente manter-se no mesmo assunto. Conte alguma curiosidade sobre um grande craque, de vez em quando.", 0.2, "M")
|
59 |
}
|
60 |
|
@@ -62,7 +65,7 @@ INITIAL_PERSON = "nova"
|
|
62 |
|
63 |
|
64 |
# Função para converter o histórico de chat para o formato esperado pela API do OpenAI
|
65 |
-
def to_openai_chat_history(system_prompt,
|
66 |
prompt = [ { 'role': 'system', 'content': system_prompt } ]
|
67 |
if len(chat_history) > 10:
|
68 |
chat_history = chat_history[0:3] + chat_history[-5:]
|
@@ -75,37 +78,83 @@ def to_openai_chat_history(system_prompt, curr_message, chat_history):
|
|
75 |
|
76 |
|
77 |
# Função para converter o histórico de chat para o formato esperado pela API do Google AI
|
78 |
-
def to_google_history(
|
79 |
prompt = []
|
80 |
for turn in chat_history:
|
81 |
user_message, bot_message = turn
|
82 |
prompt.append( {'role':'user', 'parts': [user_message]} )
|
83 |
prompt.append( {'role': 'model', 'parts': [bot_message]} )
|
84 |
-
|
|
|
|
|
85 |
|
86 |
return prompt
|
87 |
|
88 |
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
else:
|
101 |
GOOGLE_GEN_CONFIG.temperature = temperature
|
102 |
model = genai.GenerativeModel('gemini-1.5-pro-latest',
|
103 |
system_instruction=system_prompt,
|
|
|
104 |
generation_config=GOOGLE_GEN_CONFIG)
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
bot_response = model.generate_content(google_history, generation_config=GOOGLE_GEN_CONFIG)
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
assistant_msg = bot_response.text
|
111 |
|
@@ -130,15 +179,15 @@ def reset_and_apply(voice):
|
|
130 |
return [("", "Olá, vamos falar de futebol?")], AUDIO_OUT_FILE_PREFIX + f"-001-{voice}.wav"
|
131 |
|
132 |
def reset_openai_client(openai_key):
|
133 |
-
global
|
134 |
-
|
135 |
OPENAI_API_KEY = openai_key
|
136 |
if OPENAI_API_KEY != "":
|
137 |
OPENAI_CLIENT = OpenAI(api_key=OPENAI_API_KEY)
|
138 |
|
139 |
def reset_google_client(google_key):
|
140 |
-
global GOOGLE_API_KEY,
|
141 |
-
|
142 |
GOOGLE_API_KEY = google_key
|
143 |
if GOOGLE_API_KEY != "":
|
144 |
genai.configure(api_key=GOOGLE_API_KEY)
|
@@ -211,7 +260,7 @@ with gr.Blocks() as demo:
|
|
211 |
reset_btn = gr.Button("Reiniciar")
|
212 |
|
213 |
with gr.Accordion(label="Configurações",open=False):
|
214 |
-
openai_key = gr.Textbox(label="OpenAI API Key", value="", placeholder="Insira a chave aqui")
|
215 |
openai_key.change(reset_openai_client, inputs=[openai_key])
|
216 |
|
217 |
#openai_key = gr.Textbox(label="Google API Key (Gemini 1.5)", value="", placeholder="Insira a chave aqui")
|
@@ -238,3 +287,4 @@ with gr.Blocks() as demo:
|
|
238 |
|
239 |
|
240 |
demo.queue().launch(share=False)
|
|
|
|
4 |
from openai import OpenAI
|
5 |
import google.generativeai as genai
|
6 |
|
7 |
+
from match_info_crawler import get_matches_info
|
8 |
+
|
9 |
|
10 |
LOAD_KEYS_FROM_FILES = False
|
11 |
USE_LOCAL_ASR_PIPELINE = False
|
|
|
29 |
GOOGLE_API_KEY = "" if 'GOOGLE_API_KEY' not in os.environ else os.environ['GOOGLE_API_KEY']
|
30 |
assert 'HUGGINGFACE_API_KEY' in os.environ, "Hugging Face API key not found in environment variables"
|
31 |
|
32 |
+
GOOGLE_API_KEY = ""
|
33 |
+
USE_OPENAI_FOR_CHAT = (GOOGLE_API_KEY == "")
|
34 |
|
35 |
OPENAI_CLIENT = None
|
36 |
if OPENAI_API_KEY != "":
|
|
|
47 |
|
48 |
TEMPLATE_SYSTEM_MESSAGE = """Você é assistente virtual com a função é entreter uma criança de idade entre 6 e 8 anos que adora futebol. Diretrizes para a conversa:
|
49 |
- Você é {GENRE}, seu nome é {NAME}.
|
|
|
|
|
|
|
50 |
- {PERSONALITY}
|
51 |
+
- Pergunte o nome da criança.
|
52 |
+
- Fale sobre futebol, times, jogadores, seleções e grandes jogos.
|
53 |
+
- Tente focar em Brasil, Inglaterra e Espanha.
|
54 |
+
- Você também pode informar os resultados de jogos de ontem, e jogos que ocorrerão hoje ou amanhã.
|
55 |
- Fale, no máximo, três frases por mensagem.
|
56 |
"""
|
57 |
|
58 |
# Mapeia a personalidade no template e na temperatura
|
59 |
PERSONALITIES = {
|
60 |
+
"nova": ("Sua personalidade é bastante amigável e alegre, e um tanto infantil. Tente iniciar novos assuntos, quando a conversa estiver repetitiva. Conte piadas de futebol, de vez em quando.", 0.8, "F"),
|
61 |
"echo": ("Sua personalidade é amigável, mas objetivo. Tente manter-se no mesmo assunto. Conte alguma curiosidade sobre um grande craque, de vez em quando.", 0.2, "M")
|
62 |
}
|
63 |
|
|
|
65 |
|
66 |
|
67 |
# Função para converter o histórico de chat para o formato esperado pela API do OpenAI
|
68 |
+
def to_openai_chat_history(system_prompt, chat_history, curr_message):
|
69 |
prompt = [ { 'role': 'system', 'content': system_prompt } ]
|
70 |
if len(chat_history) > 10:
|
71 |
chat_history = chat_history[0:3] + chat_history[-5:]
|
|
|
78 |
|
79 |
|
80 |
# Função para converter o histórico de chat para o formato esperado pela API do Google AI
|
81 |
+
def to_google_history(chat_history, curr_user_message=None):
|
82 |
prompt = []
|
83 |
for turn in chat_history:
|
84 |
user_message, bot_message = turn
|
85 |
prompt.append( {'role':'user', 'parts': [user_message]} )
|
86 |
prompt.append( {'role': 'model', 'parts': [bot_message]} )
|
87 |
+
|
88 |
+
if curr_user_message is not None:
|
89 |
+
prompt.append( {'role': 'user', 'parts': [curr_user_message]} )
|
90 |
|
91 |
return prompt
|
92 |
|
93 |
|
94 |
+
import json
|
95 |
+
|
96 |
+
TOOLS_SPECIFICATION_OPENAI = [
|
97 |
+
{
|
98 |
+
"type": "function",
|
99 |
+
"function": {
|
100 |
+
"name": "get_matches_info",
|
101 |
+
"description": "Use this function to retrieve information about matches from the most important leagues, with the time given in Brazilian timezone.",
|
102 |
+
#+ "Returns a string with one matche per line; or empty string if the service is not available now.",
|
103 |
+
"parameters": {
|
104 |
+
"type": "object",
|
105 |
+
"properties": {
|
106 |
+
"date_str": {
|
107 |
+
"type": "string",
|
108 |
+
"description": "Must be one of these: 'yesterday', 'today' or 'tomorrow'. No other option is valid."
|
109 |
+
}
|
110 |
+
},
|
111 |
+
"required": ["date_str"],
|
112 |
+
},
|
113 |
+
}
|
114 |
+
}
|
115 |
+
]
|
116 |
|
117 |
+
def respond(system_prompt, user_message, chat_history, temperature, voice="echo"):
|
118 |
+
if USE_OPENAI_FOR_CHAT:
|
119 |
+
openai_history = to_openai_chat_history(system_prompt, chat_history, user_message)
|
120 |
+
|
121 |
+
bot_response = OPENAI_CLIENT.chat.completions.create(messages=openai_history,
|
122 |
+
temperature=temperature,
|
123 |
+
tools=TOOLS_SPECIFICATION_OPENAI,
|
124 |
+
model="gpt-3.5-turbo-0125")
|
125 |
+
bot_response = bot_response.choices[0].message
|
126 |
+
|
127 |
+
if bot_response.tool_calls:
|
128 |
+
assert bot_response.tool_calls[0].function.name == "get_matches_info", "Invalid tool call in response."
|
129 |
+
print("Processing tool call...")
|
130 |
+
|
131 |
+
date_str = json.loads(bot_response.tool_calls[0].function.arguments)["date_str"]
|
132 |
+
results = get_matches_info(date_str)
|
133 |
+
openai_history.append({"role": "function", "tool_call_id": bot_response.tool_calls[0].id, "name": bot_response.tool_calls[0].function.name, "content": results})
|
134 |
+
|
135 |
+
# nesta chamada, não passo o tools, para economizar tokens
|
136 |
+
bot_response = OPENAI_CLIENT.chat.completions.create(messages=openai_history,
|
137 |
+
temperature=temperature,
|
138 |
+
model="gpt-3.5-turbo-0125")
|
139 |
+
bot_response = bot_response.choices[0].message
|
140 |
+
|
141 |
+
assistant_msg = bot_response.content
|
142 |
|
143 |
else:
|
144 |
GOOGLE_GEN_CONFIG.temperature = temperature
|
145 |
model = genai.GenerativeModel('gemini-1.5-pro-latest',
|
146 |
system_instruction=system_prompt,
|
147 |
+
tools=[get_matches_info],
|
148 |
generation_config=GOOGLE_GEN_CONFIG)
|
149 |
|
150 |
+
# funcionava assim antes de usar tools
|
151 |
+
#google_history = to_google_history(chat_history, user_message)
|
152 |
+
#bot_response = model.generate_content(google_history, generation_config=GOOGLE_GEN_CONFIG, tools=[get_matches_info])
|
153 |
+
|
154 |
+
google_history = to_google_history(chat_history)
|
155 |
+
chat = model.start_chat(history=google_history,
|
156 |
+
enable_automatic_function_calling=True)
|
157 |
+
bot_response = chat.send_message(user_message)
|
158 |
|
159 |
assistant_msg = bot_response.text
|
160 |
|
|
|
179 |
return [("", "Olá, vamos falar de futebol?")], AUDIO_OUT_FILE_PREFIX + f"-001-{voice}.wav"
|
180 |
|
181 |
def reset_openai_client(openai_key):
|
182 |
+
global USE_OPENAI_FOR_CHAT, OPENAI_CLIENT, OPENAI_API_KEY
|
183 |
+
USE_OPENAI_FOR_CHAT = (GOOGLE_API_KEY == "")
|
184 |
OPENAI_API_KEY = openai_key
|
185 |
if OPENAI_API_KEY != "":
|
186 |
OPENAI_CLIENT = OpenAI(api_key=OPENAI_API_KEY)
|
187 |
|
188 |
def reset_google_client(google_key):
|
189 |
+
global GOOGLE_API_KEY, USE_OPENAI_FOR_CHAT
|
190 |
+
USE_OPENAI_FOR_CHAT = (google_key == "")
|
191 |
GOOGLE_API_KEY = google_key
|
192 |
if GOOGLE_API_KEY != "":
|
193 |
genai.configure(api_key=GOOGLE_API_KEY)
|
|
|
260 |
reset_btn = gr.Button("Reiniciar")
|
261 |
|
262 |
with gr.Accordion(label="Configurações",open=False):
|
263 |
+
openai_key = gr.Textbox(label="OpenAI API Key (GPT e vozes)", value="", placeholder="Insira a chave aqui")
|
264 |
openai_key.change(reset_openai_client, inputs=[openai_key])
|
265 |
|
266 |
#openai_key = gr.Textbox(label="Google API Key (Gemini 1.5)", value="", placeholder="Insira a chave aqui")
|
|
|
287 |
|
288 |
|
289 |
demo.queue().launch(share=False)
|
290 |
+
|
match_info_crawler.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import datetime
|
2 |
+
from datetime import timedelta
|
3 |
+
import pytz
|
4 |
+
|
5 |
+
from bs4 import BeautifulSoup
|
6 |
+
|
7 |
+
import requests
|
8 |
+
from datetime import datetime, timedelta
|
9 |
+
|
10 |
+
import os
|
11 |
+
import re
|
12 |
+
|
13 |
+
import google.generativeai as genai
|
14 |
+
|
15 |
+
|
16 |
+
with open('KEY_GOOGLE_AI', 'r') as file:
|
17 |
+
GOOGLE_API_KEY = file.read().replace('\n', '')
|
18 |
+
|
19 |
+
genai.configure(api_key=GOOGLE_API_KEY)
|
20 |
+
|
21 |
+
|
22 |
+
USE_BEST_EXTRACTOR = True
|
23 |
+
|
24 |
+
sao_paulo_timezone = pytz.timezone('America/Sao_Paulo')
|
25 |
+
|
26 |
+
CURRENT_DATE = datetime.now(sao_paulo_timezone)
|
27 |
+
|
28 |
+
|
29 |
+
SYSTEM_PROMPT = '''You will extract soccer match information from the text extracted from a html page,
|
30 |
+
and you have to output the matches in this format:
|
31 |
+
[TEAM HOME] [SCORE HOME] x [SCORE AWAY] [TEAM AWAY] - [CHAMPIONSHIP NAME] - [START TIME / MATCH TIME]
|
32 |
+
|
33 |
+
Regarding [START TIME / MATCH TIME]:
|
34 |
+
- if the match has already started, report the elapsed time in the match
|
35 |
+
- if it hasn't started write 'not started'
|
36 |
+
- if the match has finished, report 'finished'
|
37 |
+
|
38 |
+
More information:
|
39 |
+
- ignore matches for youth (under-20) and women leagues
|
40 |
+
- example output:
|
41 |
+
```
|
42 |
+
PSG 0 x 1 Borussia Dortmund - Champions League - finished
|
43 |
+
Palmeiras 0 x 2 Atletico Paranaense - Campeonato Brasileiro - Série A - finished
|
44 |
+
```
|
45 |
+
'''
|
46 |
+
|
47 |
+
|
48 |
+
if USE_BEST_EXTRACTOR:
|
49 |
+
EXTRACTOR_MODEL = genai.GenerativeModel('gemini-1.5-pro-latest',
|
50 |
+
system_instruction=SYSTEM_PROMPT) # TODO: setar uma temperatura bem baixa!
|
51 |
+
else:
|
52 |
+
EXTRACTOR_MODEL = genai.GenerativeModel('gemini-1.0-pro')
|
53 |
+
|
54 |
+
|
55 |
+
START_MAIS_POP_SECTION = "<h3 class='match-list_league-name'>MAIS POPULARES AGORA</h3>"
|
56 |
+
END_MAIS_POP_SECTION = "<h3 class='match-list_league-name'"
|
57 |
+
|
58 |
+
|
59 |
+
|
60 |
+
def remove_between(main_string, key1, key2, to_replace=""):
|
61 |
+
pattern = f"{key1}(.*?){key2}"
|
62 |
+
return re.sub(pattern, to_replace, main_string, flags=re.DOTALL)
|
63 |
+
|
64 |
+
|
65 |
+
def get_matches_info(date_str: str):
|
66 |
+
'''Returns matches info from all major leagues, including date and time in Brazilian timezone.
|
67 |
+
Parameters:
|
68 |
+
- date_str parameter is either 'yesterday', 'today' or 'tomorrow', in Brazilian timezone.
|
69 |
+
Returns:
|
70 |
+
- String with one matche per line; or empty string if the service is not available now.
|
71 |
+
'''
|
72 |
+
assert date_str in ['yesterday', 'today', 'tomorrow'], 'Invalid date_str parameter'
|
73 |
+
|
74 |
+
if date_str == 'yesterday':
|
75 |
+
link = 'https://www.placardefutebol.com.br/jogos-de-ontem'
|
76 |
+
date = CURRENT_DATE - timedelta(days=1)
|
77 |
+
type = 'complete'
|
78 |
+
elif date_str == 'tomorrow':
|
79 |
+
link = 'https://www.placardefutebol.com.br/jogos-de-amanha'
|
80 |
+
date = CURRENT_DATE + timedelta(days=1)
|
81 |
+
type = 'incomplete'
|
82 |
+
else:
|
83 |
+
link = 'https://www.placardefutebol.com.br/jogos-de-hoje'
|
84 |
+
date = CURRENT_DATE
|
85 |
+
type = 'incomplete'
|
86 |
+
|
87 |
+
# arquivo com nome igual ao 'date' desejado
|
88 |
+
filename = date.strftime('%Y-%m-%d') + f'-{type}.txt'
|
89 |
+
|
90 |
+
if os.path.exists(filename):
|
91 |
+
with open(filename, 'r', encoding='utf8') as file:
|
92 |
+
return file.read()
|
93 |
+
|
94 |
+
# download the page
|
95 |
+
try:
|
96 |
+
page_raw = requests.get(link)
|
97 |
+
page = page_raw.content.decode('utf-8')
|
98 |
+
except:
|
99 |
+
print('Error in downloading the page', link)
|
100 |
+
return ""
|
101 |
+
|
102 |
+
page = remove_between(page, START_MAIS_POP_SECTION, END_MAIS_POP_SECTION, END_MAIS_POP_SECTION)
|
103 |
+
|
104 |
+
parser = BeautifulSoup(page, 'html.parser')
|
105 |
+
page = parser.get_text()
|
106 |
+
|
107 |
+
plain_page = page
|
108 |
+
plain_page = plain_page[:plain_page.rfind('[+] Mais campeonatos')]
|
109 |
+
plain_page = plain_page.replace('Ver tabela e classificação', '')
|
110 |
+
|
111 |
+
plain_page = remove_between(plain_page, "Placar ao vivo de", "dos jogos de hoje.")
|
112 |
+
plain_page = remove_between(plain_page, "Aplicativo de", "Meu Mundial de Clubes")
|
113 |
+
|
114 |
+
new_text = plain_page
|
115 |
+
old_text = ''
|
116 |
+
while new_text != old_text:
|
117 |
+
old_text = new_text
|
118 |
+
new_text = old_text.replace('\n\n', '\n')
|
119 |
+
plain_page = new_text
|
120 |
+
|
121 |
+
#print("PROCESSING:\n", plain_page)
|
122 |
+
|
123 |
+
try:
|
124 |
+
if USE_BEST_EXTRACTOR:
|
125 |
+
#response = EXTRACTOR_MODEL.generate_content(plain_page)
|
126 |
+
response = EXTRACTOR_MODEL.generate_content("HTML PAGE TO BE PARSED: \n\n" + plain_page)
|
127 |
+
else:
|
128 |
+
prompt = "INSTRUCTIONS: \n\n" + SYSTEM_PROMPT + "\n\nHTML PAGE TO BE PARSED: \n\n" + plain_page
|
129 |
+
response = EXTRACTOR_MODEL.generate_content(prompt)
|
130 |
+
except Exception as e:
|
131 |
+
print('Error in generating content:')
|
132 |
+
print(e)
|
133 |
+
return ""
|
134 |
+
|
135 |
+
text_out = response.text
|
136 |
+
#text_out = text_out.replace('```json', '').replace('```', '')
|
137 |
+
text_out = text_out.replace('```', '')
|
138 |
+
|
139 |
+
# save the file
|
140 |
+
with open(filename, 'w', encoding='utf8') as file:
|
141 |
+
file.write(text_out)
|
142 |
+
|
143 |
+
return text_out
|
144 |
+
|
145 |
+
|
146 |
+
|
147 |
+
if __name__ == '__main__':
|
148 |
+
matches_info = get_matches_info('yesterday')
|
149 |
+
print(matches_info)
|
150 |
+
|