function lexical_score(query_words, doc): # e.g. BM25-style term overlap

   return sum(term_frequency(w, doc) for w in query_words if w in doc)

 function semantic_score(query_embedding, doc_embedding):
   return cosine_similarity(query_embedding, doc_embedding)
 # lexical matches exact words; semantic matches meaning even with different words
