"""ranking.py — Ordina risultati web per rilevanza + qualità.""" import re from typing import Optional def tfidf_score(query:str,document:str)->float: terms=[w.lower() for w in re.split(r"\W+",query) if len(w)>2] words=re.split(r"\W+",document.lower()); n=max(1,len(words)); score=0.0 for t in terms: score+=words.count(t)/n return score def quality_score(result:dict)->float: w={"StackOverflow":0.95,"Brave":0.90,"Tavily":0.88,"Wikipedia":0.85,"HackerNews":0.80,"DDG":0.70} base=w.get(result.get("source",""),0.60) bonus=min(0.2,len(result.get("snippet",""))/1000)+(0.1 if result.get("answered") else 0) return min(1.0,base+bonus) def rank_results(results:list[dict],query:str,top_k:int=6)->list[dict]: for r in results: r["_r"]=tfidf_score(query,f"{r.get('title','')} {r.get('snippet','')}") r["_q"]=quality_score(r); r["_s"]=0.6*r["_r"]+0.4*r["_q"] ranked=sorted(results,key=lambda x:x["_s"],reverse=True)[:top_k] for r in ranked: [r.pop(k,None) for k in ["_r","_q","_s"]] return ranked def format_for_llm(results:list[dict],query:str)->str: if not results: return f"Nessun risultato per: {query}" lines=[f"Risultati: **{query}**\n"] for i,r in enumerate(results,1): lines.append(f"{i}. **{r.get('title','')[:300]}** [{r.get('source','Web')}]") # S607: 200→300 if r.get("snippet"): lines.append(f" {r['snippet'][:300]}") # S585: 200→300 if r.get("url"): lines.append(f" {r['url']}"); lines.append("") return "\n".join(lines)