From 9f760718f0c311b270bc1ee27027395e60f28e54 Mon Sep 17 00:00:00 2001 From: localhost Date: Tue, 3 Mar 2026 17:11:29 +0100 Subject: [PATCH] better prompting --- bun.lockb | Bin 53185 -> 53201 bytes src/router/websocket.ts | 8 ++-- src/utils/slop.ts | 84 +++++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/bun.lockb b/bun.lockb index 68ff44b5468acb7e6e84f642fb5dac97c6c31d27..ff755931a44c47a451103f9963e01c4099ff62b1 100755 GIT binary patch delta 37 tcmX>&pZVf^<_Ug`jvM_OC$TUxFfeSsGAY)EBiS#_y)3BMZ*pPA3;+d74YU9N delta 28 jcmcaOpZVZ?<_Ug`h8z7GC$anog3VVZ#oA1+%$NWG%0UjW diff --git a/src/router/websocket.ts b/src/router/websocket.ts index c7e96e8..8e018f8 100644 --- a/src/router/websocket.ts +++ b/src/router/websocket.ts @@ -134,11 +134,11 @@ app.ws('/save', { return sendError(ws, 'Unable to retrieve video info from YouTube. Please try again later.') } - const slopScore = await parseSlop(videoId, data.videoDetails.title, + const isSlop = await parseSlop(videoId, data.videoDetails.title, (data.microformat.playerMicroformatRenderer.description?.simpleText || '').replaceAll('\n', '
'), data.videoDetails.channelId) - if (slopScore >= 4) { + if (isSlop) { sendError(ws, 'Filters can always be wrong. Is the rating wrong? Email me at admin@preservetube.com', false); return sendError(ws, 'Your download has been rejected by our slop filter.'); } @@ -216,10 +216,10 @@ app.ws('/savechannel', { break; } - const slopScore = await parseSlop(video.video_id, video.title.text, + const isSlop = await parseSlop(video.video_id, video.title.text, video.description_snippet?.text || '', channelId) - if (slopScore >= 4) { + if (isSlop) { sendError(ws, 'Filters can always be wrong. Is the rating wrong? Email me at admin@preservetube.com', false); sendError(ws, 'Your download has been rejected by our slop filter.'); continue; diff --git a/src/utils/slop.ts b/src/utils/slop.ts index 717064d..df2d59b 100644 --- a/src/utils/slop.ts +++ b/src/utils/slop.ts @@ -14,7 +14,8 @@ const channelBlacklist = [ 'UCUQmW2YLzhEmMTqO0RAPlOw', 'UC4Anp9y2TU-d5blFUf7wCqw', 'UC-TaLb_bURExFdLFXkJ3Adg', - 'UC1XgosSxwK9xtrMLsRzCbHw' + 'UC1XgosSxwK9xtrMLsRzCbHw', + 'UCInXezQxpWgrd7uPKeA6gPQ', ] async function analyseSlop(id: string, title: string, description: string) { @@ -25,52 +26,55 @@ async function analyseSlop(id: string, title: string, description: string) { 'Content-Type': 'application/json' }, body: JSON.stringify({ - model: 'gemini-2.5-flash-lite', + model: 'deepseek/deepseek-v3.2', messages: [ - { role: 'user', content: `Role: You are "The Slop Detector." Analyze video titles and rate them 0-5 on the "Slop Score." Slop is derivative content using popular movie/TV footage + trendy audio + basic editing. + { role: 'user', content: `You are "The Slop Detector." Analyze video titles and determine if the content is SLOP or NOT SLOP. -### SLOP SCORE (0-5) -- **0:** Original, complex, artistic. No slop signals. -- **1:** Fan edit with unique perspective, non-obvious choices. -- **2:** Well-made but predictable, adds nothing new. -- **3:** Some slop signals present, minimal effort visible. -- **4:** Textbook slop β€” popular character + overused/slowed song + 4K tag + "Edit." -- **5:** Maximum slop density β€” every possible signal stacked. - -### SLOP SIGNALS -Use these as intuition guides, not a checklist. Weight them by how many stack together. - -- **Emoji in title** β€” strong signal, especially πŸ˜‚πŸ€£πŸ˜ŽπŸ˜πŸ₯Ί. Multiple emoji = very strong. -- **Title is entirely hashtags** β€” near-instant slop. -- **Unicode styled text** (π‹π’π€πž 𝐓𝐑𝐒𝐬) β€” common in character edits. -- **Pipe separators** (|) splitting title into the classic pattern of caption | source | song β€” only a signal when used to stack multiple slop elements (e.g. character | show | slowed song). A single pipe for emphasis or listing does not count. -- **4K / [4K] tag** β€” almost always slop when paired with anything else. -- **"Edit" / "OneShot" / "Morphosis"** suffix or delimiter usage (β•‘ Edit β•‘, γ€ŒEdit」). -- **Slowed / Reverb / Slowed+Reverb / MONTAGEM** β€” only counts when stacked with others -- **Known slop franchises:** This list is definitive, not illustrative. Only the following qualify: Johnny English, Mr. Bean, Breaking Bad, Peaky Blinders, American Psycho, Patrick Bateman, The Boys, Homelander, Dexter, Joe Goldberg, Squid Game, Rick Grimes, Thomas Shelby, John Wick, Kingsman. They must be explicitly named, no interpretation from your side. -- **Song name explicitly in title** β€” especially if slowed/remixed. -- **Description** β€” if it contains hashtag spam, or music credits it reinforces slop signals from the title. -- **Clickbait** is its own category and does not affect the slop score. +### DECISION RULES +**Score SLOP if the video matches either of these categories:** +**1. Slop Edit** β€” a formulaic fan/character edit. Look for a combination of these signals: +- **Emoji in title** β€” strong signal, especially πŸ˜‚πŸ€£πŸ˜ŽπŸ˜πŸ₯Ί. Multiple emoji = very strong. (optional) +- **Title is entirely hashtags, or mostly hastags** β€” near-instant slop +- **Hashtag spam** β€” title consists of a short hook followed by 3+ hashtags, or the description is dominated by hashtags. Strong signal on its own. +- **Unicode styled text** (π‹π’π€πž 𝐓𝐑𝐒𝐬) β€” common in character edits (optional) +- **Pipe separators** (|) are only a signal when the segments themselves are slop elements (character name | franchise | song title). Pipes used for general formatting, listing topics, or separating unrelated phrases do not count under any circumstances. +- **4K / [4K] tag** β€” strong signal when paired with anything else (optional) +- **"Edit" / "OneShot" / "Morphosis"** as suffix or with delimiters (β•‘ Edit β•‘, γ€ŒEdit」) +- **Slowed / Reverb / Slowed+Reverb / MONTAGEM** β€” only counts when stacked with other signals +- **Known slop franchises** β€” this list is exhaustive, not illustrative. Only these qualify: Johnny English, Mr. Bean, Breaking Bad, Peaky Blinders, American Psycho, Patrick Bateman, The Boys, Homelander, Dexter, Joe Goldberg, Squid Game, Rick Grimes, Thomas Shelby, John Wick, Kingsman. Must be explicitly named. +- **Song name explicitly in title** β€” especially if slowed or remixed +- **Description** β€” hashtag spam or music credits reinforce title signals +- **Title mirrors description exactly** β€” reinforces slop when combined with other signals (optional) +**2. Raw clip** β€” an unedited or minimally edited fragment of a TV show or movie with no transformative content. +**3. AI-generated compilation** β€” footage generated by AI tools. Score SLOP if: +- Title or description explicitly mentions "Sora" ### EXCEPTIONS -- Tutorials, news, commentary, politics β€” score 0 automatically -- Lost/archived content β€” score 0 automatically -- Fan animations/original franchise-inspired art β€” do not trigger slop -- Direct movie/TV clips or scenes uploaded without transformative editing β€” score 4 automatically +Always score NOT SLOP: +- News, commentary, politics +- Lost or archived content + +### NOTES +- Emoji alone does not make something slop +- A character reference alone does not make something slop +- Pipes and emoji together are not sufficient for a SLOP ruling without additional corroborating signals +- ASMR, art, cooking, and similar creator content is NOT slop even if it uses emoji or pipes +- Do not infer or assume anything about creators, channels, or franchises not explicitly listed in the known slop franchises. If it's not on the list, it's not a signal. +- A channel with social links, Discord, Patreon, and editor credits in the description is a legitimate creator, not a slop channel ### OUTPUT -Valid JSON only. No other text. One sentence reasoning max, be brief. Use your judgment β€” if multiple signals stack logically toward slop, score accordingly. Do not assume content type beyond what title explicitly states. +Valid JSON only. No other text. One sentence reasoning max, be brief. -{"score": 0, "reasoning": "..."} +{"is_slop": true/false, "reasoning": "..."} User Title: ${title} -User Description: ${description.slice(0,100)}` } +User Description: ${description.slice(0,500)}` } ] }) })).json() - let parsedResponse: {score: number, reasoning: string} - = { score: 0, reasoning: 'failed to parse' } + let parsedResponse: {is_slop: boolean, reasoning: string} + = { is_slop: false, reasoning: 'failed to parse' } try { parsedResponse = JSON.parse(llmResponse.choices[0].message.content.replace(/```json|```/g, '').trim()) @@ -82,16 +86,16 @@ User Description: ${description.slice(0,100)}` } return parsedResponse } -async function parseSlop(id: string, title: string, description: string, channelId: string): Promise { - if (channelBlacklist.includes(channelId)) return 5; +async function parseSlop(id: string, title: string, description: string, channelId: string): Promise { + if (channelBlacklist.includes(channelId)) return true; const cachedSlop = await redis.get(`slop:${id}`) - if (cachedSlop) return parseInt(cachedSlop) + if (cachedSlop) return Boolean(cachedSlop) - const { score, reasoning } = await analyseSlop(id , title, description) - if (reasoning != 'failed to parse') await redis.set(`slop:${id}`, score, 'EX', 60 * 60 * 24 * 7) + const { is_slop, reasoning } = await analyseSlop(id , title, description) + if (reasoning != 'failed to parse') await redis.set(`slop:${id}`, is_slop.toString(), 'EX', 60 * 60 * 24 * 7) - return score + return is_slop } export { parseSlop } \ No newline at end of file