feat(link-summ): improve YouTube summaries using oEmbed title/thumbnail hints; keep prompt link-only

This commit is contained in:
Thomas Cravey 2025-08-17 19:13:18 -05:00
parent fed806bfc0
commit e9d764817f

View file

@ -2,6 +2,7 @@ package summarizer
import ( import (
"context" "context"
"encoding/json"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@ -172,9 +173,42 @@ func (o *OpenAI) SummarizeLink(ctx context.Context, rawURL string) (string, erro
client := openai.NewClientWithConfig(cfg) client := openai.NewClientWithConfig(cfg)
content := "" content := ""
title := ""
img := "" img := ""
lu, _ := url.Parse(rawURL)
host := strings.ToLower(lu.Host)
isYouTube := host == "www.youtube.com" || host == "youtube.com" || host == "m.youtube.com" || host == "youtu.be"
if isImageURL(rawURL) { if isImageURL(rawURL) {
img = rawURL img = rawURL
} else if isYouTube {
// YouTube: try oEmbed for title + thumbnail
watchURL := rawURL
if host == "youtu.be" {
id := strings.TrimPrefix(lu.Path, "/")
watchURL = "https://www.youtube.com/watch?v=" + id
}
ctx2, cancel := context.WithTimeout(ctx, o.linkTimeout)
defer cancel()
oembed := "https://www.youtube.com/oembed?format=json&url=" + url.QueryEscape(watchURL)
req, _ := http.NewRequestWithContext(ctx2, http.MethodGet, oembed, nil)
if resp, err := http.DefaultClient.Do(req); err == nil {
func(){
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
var oem struct{
Title string `json:"title"`
Thumb string `json:"thumbnail_url"`
}
if err := json.NewDecoder(resp.Body).Decode(&oem); err == nil {
if oem.Title != "" { title = oem.Title }
if oem.Thumb != "" { img = oem.Thumb }
}
}
}()
}
// No robust transcript grab here; rely on model generalization + title
} else if o.followLinks { } else if o.followLinks {
ctx2, cancel := context.WithTimeout(ctx, o.linkTimeout) ctx2, cancel := context.WithTimeout(ctx, o.linkTimeout)
defer cancel() defer cancel()
@ -192,14 +226,13 @@ func (o *OpenAI) SummarizeLink(ctx context.Context, rawURL string) (string, erro
if art, err := readability.FromReader(strings.NewReader(text), base); err == nil { if art, err := readability.FromReader(strings.NewReader(text), base); err == nil {
if at := strings.TrimSpace(art.TextContent); at != "" { if at := strings.TrimSpace(art.TextContent); at != "" {
text = at text = at
if title == "" && strings.TrimSpace(art.Title) != "" { title = strings.TrimSpace(art.Title) }
} }
} }
} }
text = strings.ReplaceAll(text, "\r", "") text = strings.ReplaceAll(text, "\r", "")
text = strings.TrimSpace(text) text = strings.TrimSpace(text)
if len(text) > 6000 { if len(text) > 6000 { text = text[:6000] }
text = text[:6000]
}
content = text content = text
} }
}() }()
@ -213,7 +246,9 @@ func (o *OpenAI) SummarizeLink(ctx context.Context, rawURL string) (string, erro
b := strings.Builder{} b := strings.Builder{}
b.WriteString("URL: ") b.WriteString("URL: ")
b.WriteString(rawURL) b.WriteString(rawURL)
b.WriteString("\n\n") b.WriteString("\n")
if title != "" { b.WriteString("Title: "); b.WriteString(title); b.WriteString("\n") }
b.WriteString("\n")
if content != "" { if content != "" {
b.WriteString("Extracted content (may be truncated):\n") b.WriteString("Extracted content (may be truncated):\n")
b.WriteString(content) b.WriteString(content)
@ -239,17 +274,11 @@ func (o *OpenAI) SummarizeLink(ctx context.Context, rawURL string) (string, erro
}, },
MaxCompletionTokens: o.maxTokens, MaxCompletionTokens: o.maxTokens,
} }
if !reasoningLike { if !reasoningLike { req.Temperature = 0.2 }
req.Temperature = 0.2
}
resp, err := client.CreateChatCompletion(ctx, req) resp, err := client.CreateChatCompletion(ctx, req)
if err != nil { if err != nil { return "", err }
return "", err if len(resp.Choices) == 0 { return "", nil }
}
if len(resp.Choices) == 0 {
return "", nil
}
return strings.TrimSpace(resp.Choices[0].Message.Content), nil return strings.TrimSpace(resp.Choices[0].Message.Content), nil
} }