Spaces:
Sleeping
Sleeping
import logging | |
import os | |
from logging import getLogger | |
import gradio as gr | |
from google import genai | |
from google.genai import types | |
logger = getLogger(__name__) | |
# Configure logger to show info level messages | |
logging.basicConfig(level=logging.INFO) | |
logger.setLevel(logging.INFO) | |
logger.info("Logger configured to show INFO level messages") | |
def get_sources(response): | |
"""Zbiera źródła z groundingMetadata""" | |
try: | |
if not response.candidates or not response.candidates[0].grounding_metadata: | |
logger.info("Brak grounding metadata - brak źródeł") | |
return [] | |
grounding_meta = response.candidates[0].grounding_metadata | |
chunks = grounding_meta.grounding_chunks | |
if not chunks: | |
logger.info("Brak chunks - brak źródeł") | |
return [] | |
# Zbierz unikalne źródła z URI | |
sources = [] | |
seen_uris = set() | |
for chunk in chunks: | |
if chunk.web and chunk.web.uri: | |
uri = chunk.web.uri | |
if uri not in seen_uris: | |
seen_uris.add(uri) | |
# Spróbuj wyciągnąć tytuł z chunk jeśli dostępny | |
title = getattr(chunk.web, 'title', '') if hasattr(chunk.web, 'title') else '' | |
if not title: | |
# Jeśli brak tytułu, użyj domeny z URL | |
from urllib.parse import urlparse | |
parsed = urlparse(uri) | |
title = parsed.netloc or uri | |
sources.append({ | |
'title': title, | |
'url': uri | |
}) | |
logger.info(f"Znaleziono {len(sources)} unikalnych źródeł") | |
return sources | |
except Exception as e: | |
logger.error(f"Błąd podczas zbierania źródeł: {e}", exc_info=True) | |
return [] | |
def format_sources_section(sources): | |
"""Formatuje sekcję źródeł""" | |
if not sources: | |
return "" | |
sources_text = "\n\n## Źródła:\n" | |
for i, source in enumerate(sources, 1): | |
sources_text += f"{i}. [{source['title']}]({source['url']})\n" | |
return sources_text | |
def generate(link: str, request: gr.Request): | |
"""Funkcja pobierająca link od użytkownika i generująca streszczenie.""" | |
# Pokaż loading state na początku | |
yield "🔄 **Generuję streszczenie artykułu...**\n\nProszę czekać, może to potrwać kilka chwil." | |
try: | |
client = genai.Client( | |
vertexai=False, | |
api_key=os.getenv("GOOGLE_API_KEY") | |
) | |
prompt = f""" | |
Otrzymujesz link do artykułu. Twoje zadanie to przygotowanie syntetycznego streszczenia na potrzeby YouTube oraz social media. | |
Zwróć wynik w następującej strukturze: | |
## Tytuł: | |
Przepisz dokładnie tytuł artykułu | |
## Podsumowanie: | |
Jedno-dwa zdania, które jasno wyjaśniają, czego dotyczy artykuł. | |
## Sugestie do odcinka YouTube: | |
Wypunktuj rzeczy, które warto poruszyć w odcinku (najważniejsze wątki, ciekawe fakty, potencjalne tematy do rozwinięcia): | |
- Opis tematu - dodatkowe wyjaśnienie | |
- Kolejny temat - kontekst | |
## Najważniejsze informacje: | |
Zbierz kluczowe dane i fakty, nie pomijaj liczb, wyników, cytowanych źródeł: | |
- Konkretny fakt/liczba/wynik - kontekst i wyjaśnienie | |
- Następna informacja - dodatkowe szczegóły | |
## Cytaty z artykułu: | |
Jeśli w artykule są cytaty bohaterów lub ekspertów, wypisz je w formacie: | |
> **"pełny cytat"** - imię i nazwisko osoby, stanowisko | |
Pogrub najważniejsze fragmenty cytatów. Nie wymyślaj cytatów, jeśli ich nie ma – pomiń ten punkt. | |
## Ciekawostki: | |
Jeśli w artykule pojawiają się ciekawe lub zaskakujące informacje, wypisz je tutaj. Możesz dodać dodatkowe fakty znalezione w internecie, pod warunkiem, że są aktualne i zgodne z treścią artykułu: | |
- Ciekawa informacja - dodatkowy kontekst | |
- Dodatkowy fakt z internetu - wyjaśnienie pochodzenia | |
## Timestamp do odcinka YouTube: | |
Zaproponuj timestamp w formacie: | |
- 00:00 **Wprowadzenie** | |
- 02:30 **Główne wątki** | |
- 05:00 **Najważniejsze fakty** | |
- 08:00 **Podsumowanie** | |
### ZASADY: | |
- Wszystko musi być zgodne z treścią artykułu | |
- Nie wymyślaj cytatów ani faktów | |
- Jeśli dany punkt nie występuje w artykule, pomiń go bez komentarza | |
- Używaj pogrubień (**tekst**) dla kluczowych informacji | |
- NIE dodawaj linków markdown - będą dodane automatycznie | |
Źródło: {link} | |
""" | |
model = "gemini-2.5-flash" | |
# Uproszczona konfiguracja - użyj prompt jako string | |
tools = [ | |
types.Tool(google_search=types.GoogleSearch()), | |
] | |
generate_content_config = types.GenerateContentConfig( | |
temperature=0.0, | |
top_p=0.95, | |
max_output_tokens=8192, | |
tools=tools, | |
) | |
# Wygeneruj odpowiedź (bez streamingu) | |
response = client.models.generate_content( | |
model=model, | |
contents=prompt, | |
config=generate_content_config, | |
) | |
if response and response.text: | |
# Zbierz źródła z groundingMetadata | |
sources = get_sources(response) | |
# Loguj informacje o groundingu | |
if (response.candidates and response.candidates[0].grounding_metadata): | |
grounding_meta = response.candidates[0].grounding_metadata | |
if hasattr(grounding_meta, 'web_search_queries'): | |
logger.info(f"Zapytania wyszukiwania: {grounding_meta.web_search_queries}") | |
if hasattr(grounding_meta, 'grounding_chunks') and grounding_meta.grounding_chunks: | |
logger.info(f"Liczba źródeł: {len(grounding_meta.grounding_chunks)}") | |
# Połącz odpowiedź z sekcją źródeł | |
final_result = response.text + format_sources_section(sources) | |
yield final_result | |
else: | |
yield "❌ **Błąd:** Nie udało się wygenerować streszczenia. Spróbuj ponownie." | |
except Exception as e: | |
# Return error message | |
yield f"❌ **Błąd:** {str(e)}" | |
with gr.Blocks() as demo: | |
_ = gr.Markdown("## Streszczenia newsów\nWklej link do artykułu, a wygeneruję z niego najważniejsze informacje w formie podsumowania i punktów.") | |
with gr.Row(): | |
link_input = gr.Textbox(label="Link do artykułu", placeholder="https://akademiatriathlonu.pl/...") | |
output = gr.Markdown(label="Streszczenie") | |
submit_btn = gr.Button("Generuj streszczenie") | |
_ = submit_btn.click(fn=generate, inputs=[link_input], outputs=[output]) | |
_ = demo.launch(show_error=True) |