feat: RSS embeddings, semantic news in chat, article-to-chat, richer briefings

- Embed RSS items at fetch time (nomic-embed-text); backfill at startup
- Semantic news search injected into chat system prompt ("Recent News You've Seen")
  when items match query above 0.55 cosine threshold (independent of note RAG)
- "Discuss in chat" button on news cards — creates a seeded conversation with
  the article title + full content, navigates directly to the new chat
- Briefing compilation now passes 500-char article excerpts (not just headlines)
  to the LLM and uses 8192 num_ctx to accommodate the larger prompt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 15:12:38 -04:00
parent dba41879ed
commit a773c11aa0
11 changed files with 327 additions and 8 deletions
+27
View File
@@ -668,6 +668,33 @@ async def build_context(
+ "\n--- End Included Notes ---"
)
# Search for semantically relevant recent news items
try:
from fabledassistant.services.embeddings import get_embedding, semantic_search_rss_items
news_query_vec = await get_embedding(user_message)
news_hits = await semantic_search_rss_items(user_id, news_query_vec)
if news_hits:
news_snippets = []
for score, rss_item in news_hits:
feed_title = getattr(rss_item, "feed_title", "") or ""
excerpt = (rss_item.content or "")[:500].strip()
news_snippets.append(
f"[{feed_title or 'News'}] {rss_item.title} (relevance: {round(score * 100)}%)\n"
+ (f"{excerpt}\n" if excerpt else "")
+ f"URL: {rss_item.url}"
)
system_parts.append(
"\n\n--- Recent News You've Seen ---\n"
+ "\n\n".join(news_snippets)
+ "\n--- End Recent News ---"
)
context_meta["rss_news"] = [
{"id": item.id, "title": item.title, "score": round(score, 2)}
for score, item in news_hits
]
except Exception:
logger.debug("RSS semantic search skipped", exc_info=True)
# Fetch URL content from user message
urls = _find_urls(user_message)
for url in urls[:2]: # Limit to 2 URLs