Instructions to use amogaddy/GenerAI with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use amogaddy/GenerAI with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="amogaddy/GenerAI")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("amogaddy/GenerAI", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use amogaddy/GenerAI with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "amogaddy/GenerAI" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "amogaddy/GenerAI", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/amogaddy/GenerAI
- SGLang
How to use amogaddy/GenerAI with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "amogaddy/GenerAI" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "amogaddy/GenerAI", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "amogaddy/GenerAI" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "amogaddy/GenerAI", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use amogaddy/GenerAI with Docker Model Runner:
docker model run hf.co/amogaddy/GenerAI
Fix: DuckDuckGo bloccava le richieste automatizzate, sostituito con Bing (testato e funzionante)
Browse files- scraper.py +94 -35
scraper.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
| 2 |
import trafilatura
|
| 3 |
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError
|
| 4 |
from errors import get_logger, GenerAIError, ErrorCode, fmt_exc
|
| 5 |
|
| 6 |
log = get_logger("scraper")
|
| 7 |
|
| 8 |
-
SEARCH_URL = "https://
|
| 9 |
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
| 10 |
NAV_TIMEOUT_MS = 15000
|
| 11 |
|
|
@@ -17,23 +19,42 @@ def _launch_browser(p):
|
|
| 17 |
)
|
| 18 |
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
def _search_links(page, query: str, max_results: int) -> list[dict]:
|
| 21 |
-
"""Cerca su
|
| 22 |
-
url = f"{SEARCH_URL}?q={quote(query)}&
|
| 23 |
page.goto(url, timeout=NAV_TIMEOUT_MS, wait_until="domcontentloaded")
|
| 24 |
|
| 25 |
hits = []
|
| 26 |
-
rows = page.locator(".
|
| 27 |
for row in rows:
|
| 28 |
try:
|
| 29 |
-
link = row.locator("a
|
|
|
|
|
|
|
| 30 |
href = link.get_attribute("href")
|
| 31 |
-
title = link.
|
| 32 |
-
if not href
|
| 33 |
continue
|
| 34 |
-
snippet_el = row.locator(".
|
| 35 |
-
snippet = snippet_el.
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
| 37 |
except Exception:
|
| 38 |
continue
|
| 39 |
return hits
|
|
@@ -53,49 +74,36 @@ def _extract_text(page, url: str, snippet: str) -> str | None:
|
|
| 53 |
no_fallback=False,
|
| 54 |
)
|
| 55 |
except PlaywrightTimeoutError:
|
| 56 |
-
log.
|
| 57 |
text = None
|
| 58 |
except Exception as e:
|
| 59 |
-
log.
|
| 60 |
text = None
|
| 61 |
|
| 62 |
-
|
| 63 |
-
if not text or len(text) < 100:
|
| 64 |
text = snippet
|
| 65 |
-
|
| 66 |
-
if not text or len(text) < 50:
|
| 67 |
return None
|
| 68 |
return text[:2000]
|
| 69 |
|
| 70 |
|
| 71 |
-
def
|
| 72 |
-
"""Cerca
|
| 73 |
-
|
| 74 |
-
Ritorna [] se la ricerca fallisce completamente. Interfaccia invariata
|
| 75 |
-
rispetto alla precedente implementazione basata su SearXNG.
|
| 76 |
-
"""
|
| 77 |
-
log.info("Ricerca web (Chromium) per: %r", query)
|
| 78 |
-
|
| 79 |
try:
|
| 80 |
with sync_playwright() as p:
|
| 81 |
browser = _launch_browser(p)
|
| 82 |
-
context = browser.new_context(user_agent=USER_AGENT)
|
| 83 |
page = context.new_page()
|
| 84 |
try:
|
| 85 |
hits = _search_links(page, query, max_results)
|
| 86 |
except PlaywrightTimeoutError:
|
| 87 |
-
log.warning("[%s] Timeout ricerca
|
| 88 |
hits = []
|
| 89 |
except Exception as e:
|
| 90 |
-
log.warning("[%s] Ricerca
|
| 91 |
hits = []
|
| 92 |
|
| 93 |
-
if not hits:
|
| 94 |
-
browser.close()
|
| 95 |
-
log.warning("[%s] Nessun risultato per: %r", ErrorCode.WEB_NO_RESULTS.value, query)
|
| 96 |
-
return []
|
| 97 |
-
|
| 98 |
-
results = []
|
| 99 |
for hit in hits:
|
| 100 |
if len(results) >= max_results:
|
| 101 |
break
|
|
@@ -112,8 +120,59 @@ def search_and_extract(query: str, max_results: int = 3) -> list[dict]:
|
|
| 112 |
err = GenerAIError(ErrorCode.WEB_SEARCH_FAILED, f"Browser Chromium non avviato: {fmt_exc(e)}", cause=e)
|
| 113 |
err.log(log)
|
| 114 |
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
|
| 116 |
if not results:
|
| 117 |
-
log.warning("[%s] Nessun
|
| 118 |
|
| 119 |
return results
|
|
|
|
| 1 |
+
import base64
|
| 2 |
+
from urllib.parse import quote, urlparse, parse_qs
|
| 3 |
+
import requests
|
| 4 |
import trafilatura
|
| 5 |
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError
|
| 6 |
from errors import get_logger, GenerAIError, ErrorCode, fmt_exc
|
| 7 |
|
| 8 |
log = get_logger("scraper")
|
| 9 |
|
| 10 |
+
SEARCH_URL = "https://www.bing.com/search"
|
| 11 |
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
| 12 |
NAV_TIMEOUT_MS = 15000
|
| 13 |
|
|
|
|
| 19 |
)
|
| 20 |
|
| 21 |
|
| 22 |
+
def _decode_bing_redirect(href: str) -> str:
|
| 23 |
+
"""Bing avvolge i link organici in redirect di tracking (bing.com/ck/a?...&u=<base64>)."""
|
| 24 |
+
if "bing.com/ck/a" not in href:
|
| 25 |
+
return href
|
| 26 |
+
try:
|
| 27 |
+
u = parse_qs(urlparse(href).query).get("u", [""])[0]
|
| 28 |
+
if u.startswith("a1"):
|
| 29 |
+
u = u[2:]
|
| 30 |
+
pad = "=" * (-len(u) % 4)
|
| 31 |
+
return base64.urlsafe_b64decode(u + pad).decode("utf-8", errors="ignore")
|
| 32 |
+
except Exception:
|
| 33 |
+
return href
|
| 34 |
+
|
| 35 |
+
|
| 36 |
def _search_links(page, query: str, max_results: int) -> list[dict]:
|
| 37 |
+
"""Cerca su Bing e restituisce [{title, url, snippet}]."""
|
| 38 |
+
url = f"{SEARCH_URL}?q={quote(query)}&setlang=it"
|
| 39 |
page.goto(url, timeout=NAV_TIMEOUT_MS, wait_until="domcontentloaded")
|
| 40 |
|
| 41 |
hits = []
|
| 42 |
+
rows = page.locator("li.b_algo").all()[: max_results * 2]
|
| 43 |
for row in rows:
|
| 44 |
try:
|
| 45 |
+
link = row.locator("h2 a").first
|
| 46 |
+
if not link.count():
|
| 47 |
+
continue
|
| 48 |
href = link.get_attribute("href")
|
| 49 |
+
title = link.text_content() or ""
|
| 50 |
+
if not href:
|
| 51 |
continue
|
| 52 |
+
snippet_el = row.locator("p, .b_lineclamp2, .b_lineclamp3, .b_lineclamp4").first
|
| 53 |
+
snippet = snippet_el.text_content() if snippet_el.count() else ""
|
| 54 |
+
real_url = _decode_bing_redirect(href)
|
| 55 |
+
if not real_url.startswith("http"):
|
| 56 |
+
continue
|
| 57 |
+
hits.append({"title": title.strip(), "url": real_url, "snippet": (snippet or "").strip()})
|
| 58 |
except Exception:
|
| 59 |
continue
|
| 60 |
return hits
|
|
|
|
| 74 |
no_fallback=False,
|
| 75 |
)
|
| 76 |
except PlaywrightTimeoutError:
|
| 77 |
+
log.debug("Timeout caricamento pagina: %s", url)
|
| 78 |
text = None
|
| 79 |
except Exception as e:
|
| 80 |
+
log.debug("Fetch fallito per %s — %s", url, fmt_exc(e))
|
| 81 |
text = None
|
| 82 |
|
| 83 |
+
if not text or len(text) < 80:
|
|
|
|
| 84 |
text = snippet
|
| 85 |
+
if not text or len(text) < 20:
|
|
|
|
| 86 |
return None
|
| 87 |
return text[:2000]
|
| 88 |
|
| 89 |
|
| 90 |
+
def _chromium_search(query: str, max_results: int) -> list[dict]:
|
| 91 |
+
"""Cerca ed estrae testo usando Chromium headless (Playwright) via Bing."""
|
| 92 |
+
results: list[dict] = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
try:
|
| 94 |
with sync_playwright() as p:
|
| 95 |
browser = _launch_browser(p)
|
| 96 |
+
context = browser.new_context(user_agent=USER_AGENT, locale="it-IT")
|
| 97 |
page = context.new_page()
|
| 98 |
try:
|
| 99 |
hits = _search_links(page, query, max_results)
|
| 100 |
except PlaywrightTimeoutError:
|
| 101 |
+
log.warning("[%s] Timeout ricerca Bing per: %r", ErrorCode.WEB_SEARCH_FAILED.value, query)
|
| 102 |
hits = []
|
| 103 |
except Exception as e:
|
| 104 |
+
log.warning("[%s] Ricerca Bing fallita: %s", ErrorCode.WEB_SEARCH_FAILED.value, fmt_exc(e))
|
| 105 |
hits = []
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
for hit in hits:
|
| 108 |
if len(results) >= max_results:
|
| 109 |
break
|
|
|
|
| 120 |
err = GenerAIError(ErrorCode.WEB_SEARCH_FAILED, f"Browser Chromium non avviato: {fmt_exc(e)}", cause=e)
|
| 121 |
err.log(log)
|
| 122 |
return []
|
| 123 |
+
return results
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def _wikipedia_search(query: str) -> list[dict]:
|
| 127 |
+
"""Fallback diretto su Wikipedia italiana + inglese."""
|
| 128 |
+
results = []
|
| 129 |
+
for lang in ("it", "en"):
|
| 130 |
+
if len(results) >= 2:
|
| 131 |
+
break
|
| 132 |
+
try:
|
| 133 |
+
api = f"https://{lang}.wikipedia.org/w/api.php"
|
| 134 |
+
s = requests.get(api, params={
|
| 135 |
+
"action": "query", "list": "search",
|
| 136 |
+
"srsearch": query, "format": "json", "srlimit": 2,
|
| 137 |
+
}, timeout=8, headers={"User-Agent": "GenerAI/3.0"})
|
| 138 |
+
if s.status_code != 200:
|
| 139 |
+
continue
|
| 140 |
+
for hit in s.json().get("query", {}).get("search", []):
|
| 141 |
+
title = hit["title"]
|
| 142 |
+
p = requests.get(api, params={
|
| 143 |
+
"action": "query", "prop": "extracts",
|
| 144 |
+
"exintro": "1", "explaintext": "1",
|
| 145 |
+
"titles": title, "format": "json",
|
| 146 |
+
}, timeout=8, headers={"User-Agent": "GenerAI/3.0"})
|
| 147 |
+
if p.status_code != 200:
|
| 148 |
+
continue
|
| 149 |
+
for page in p.json().get("query", {}).get("pages", {}).values():
|
| 150 |
+
extract = page.get("extract", "").strip()
|
| 151 |
+
if len(extract) > 50:
|
| 152 |
+
results.append({
|
| 153 |
+
"title": page["title"],
|
| 154 |
+
"url": f"https://{lang}.wikipedia.org/wiki/{page['title'].replace(' ', '_')}",
|
| 155 |
+
"text": extract[:2000],
|
| 156 |
+
})
|
| 157 |
+
break
|
| 158 |
+
except Exception as e:
|
| 159 |
+
log.debug("Wikipedia %s fallita: %s", lang, fmt_exc(e))
|
| 160 |
+
if results:
|
| 161 |
+
log.info("Wikipedia fallback → %d risultati", len(results))
|
| 162 |
+
return results
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
def search_and_extract(query: str, max_results: int = 3) -> list[dict]:
|
| 166 |
+
"""Cerca sul web con Chromium (Playwright, Bing) + fallback Wikipedia. Estrae testo pulito."""
|
| 167 |
+
log.info("Ricerca web (Chromium) per: %r", query)
|
| 168 |
+
|
| 169 |
+
results = _chromium_search(query, max_results)
|
| 170 |
+
|
| 171 |
+
if not results:
|
| 172 |
+
log.info("Chromium non ha prodotto risultati — provo Wikipedia...")
|
| 173 |
+
results = _wikipedia_search(query)
|
| 174 |
|
| 175 |
if not results:
|
| 176 |
+
log.warning("[%s] Nessun risultato per: %r", ErrorCode.WEB_NO_RESULTS.value, query)
|
| 177 |
|
| 178 |
return results
|