class Event::Summarizer
include Ai::Prompts
include Rails.application.routes.url_helpers
attr_reader :events
LLM_MODEL = "gpt-5-chat-latest"
PROMPT = <<~PROMPT
Help me make sense of the week’s activity in a news style format with bold headlines and short summaries.
- Pick the top items to help me see patterns and milestones that I might not pick up on by looking at each individual entry.
- Use a conversational tone without business speak.
- Link to the issues naturally in context when possible, *do not* mention card numbers directly.
# Use this format:
- A single lead headline (### heading level 3) and blurb at the top that captures the overall theme of the week.
- Then 6 (or fewer) headlines (#### heading level 4) and blurbs for the most important stories.
- *Do not* add
elements.
- *Do not* insert a closing summary at the end.
Markdown link format: [anchor text](/full/path/).
- Preserve the path exactly as provided (including the leading "/").
- When linking to a Collection, paths should be in this format: (/[account id slug]/cards?collection_ids[]=x)
PROMPT
def initialize(events, prompt: PROMPT, llm_model: LLM_MODEL)
@events = events
@prompt = prompt
@llm_model = llm_model
end
def summarized_content
llm_response.content
end
def cost
Ai::UsageCost.from_llm_response(llm_response)
end
def summarizable_content
join_prompts events.collect(&:to_prompt)
end
private
attr_reader :prompt, :llm_model
MAX_TOKENS = 128000
def llm_response
@llm_response ||= chat.ask Ai::Tokenizer.truncate(llm_query, max_input_tokens: MAX_TOKENS, model: llm_model)
end
def llm_query
join_prompts("Summarize the following content:", summarizable_content)
end
def chat
chat = RubyLLM.chat(model: llm_model)
chat.with_instructions(join_prompts(prompt, domain_model_prompt, user_data_injection_prompt))
end
end