This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# retoor <retoor@molodetz.nl>
import json
import logging
import random
import re
import time
from typing import Any, Optional
import httpx
from devplacepy import stealth
from devplacepy.services.bot.config import (
GIST_LANGUAGES,
GIST_MIN_LINES,
PERSONA_GIST_FLAVOR,
PERSONA_LANGUAGES,
SEARCH_TERMS,
TRIVIAL_GIST_TERMS,
)
from devplacepy.services.bot.handles import MAX_HANDLE_LEN, sanitize_handle
HANDLE_CANDIDATE_TARGET = 8
logger = logging.getLogger(__name__)
class LLMClient:
def __init__(
self,
api_key: str,
api_url: str,
model: str,
input_cost_per_1m: float,
output_cost_per_1m: float,
gist_min_lines: int = GIST_MIN_LINES,
):
if not api_key:
raise RuntimeError("LLM API key not set")
self.api_key = api_key
self.api_url = api_url
self.model = model
self.input_cost_per_1m = input_cost_per_1m
self.output_cost_per_1m = output_cost_per_1m
self.gist_min_lines = max(1, gist_min_lines)
self.total_cost = 0.0
self.total_calls = 0
self.total_in_tokens = 0
self.total_out_tokens = 0
def _raw_call(self, system: str, prompt: str, temperature: float = 0.7) -> str:
for attempt in range(3):
try:
payload = {
"model": self.model,
"messages": [
{"role": "system", "content": system},
{"role": "user", "content": prompt},
],
"temperature": temperature,
}
logger.info(
"LLM >>> model=%s system=%s prompt=%s",
self.model,
json.dumps(system[:500]),
json.dumps(prompt[:500]),
)
with stealth.stealth_sync_client(timeout=30) as client:
resp = client.post(
self.api_url,
json=payload,
headers={"Authorization": f"Bearer {self.api_key}"},
)
raw = resp.content
logger.info("LLM <<< %s", raw[:2000].decode(errors="replace"))
result = resp.json()
usage = result.get("usage", {})
in_tokens = usage.get("prompt_tokens", 0)
out_tokens = usage.get("completion_tokens", 0)
cost = (in_tokens * self.input_cost_per_1m / 1_000_000) + (
out_tokens * self.output_cost_per_1m / 1_000_000
)
self.total_cost += cost
self.total_calls += 1
self.total_in_tokens += in_tokens
self.total_out_tokens += out_tokens
return result["choices"][0]["message"]["content"]
except (
httpx.HTTPError,
json.JSONDecodeError,
KeyError,
) as e:
logger.warning("LLM call attempt %d/3 failed: %s", attempt + 1, e)
if attempt == 2:
raise
time.sleep(2**attempt)
return ""
def _call(self, system: str, prompt: str, temperature: float = 0.7) -> str:
return self.clean(self._raw_call(system, prompt, temperature))
@staticmethod
def clean(text: str, preserve_md: bool = False) -> str:
if not preserve_md:
text = re.sub(r"\*\*|__|\*|_", "", text)
text = text.replace("", "-").replace("", "-")
text = text.replace("", "'").replace("", "'")
text = text.replace("", '"').replace("", '"')
text = re.sub(r"\s{2,}", " ", text)
return text.strip()
@staticmethod
def strip_md(text: str) -> str:
return LLMClient.clean(text)[:200]
@staticmethod
def strip_label(text: str) -> str:
labels = (
"post title",
"project name",
"snippet name",
"title",
"name",
"concept",
"snippet",
"headline",
"gist",
"issue",
)
result = (text or "").strip().strip('"').strip("'").strip()
changed = True
while changed:
changed = False
lowered = result.lower()
for label in labels:
if lowered.startswith(label + ":"):
result = result[len(label) + 1 :].strip().strip('"').strip("'")
changed = True
break
for sep in (" concept:", " description:", " desc:", " idea:"):
idx = result.lower().find(sep)
if idx > 0:
result = result[:idx].strip()
return result.strip().strip('"').strip("'").strip()
@staticmethod
def strip_code_fences(text: str) -> str:
text = text.strip()
if text.startswith("```"):
lines = text.split("\n")
if lines and lines[0].lstrip().startswith("```"):
lines = lines[1:]
if lines and lines[-1].strip().startswith("```"):
lines = lines[:-1]
text = "\n".join(lines)
return text.strip()
def generate_post(
self,
title: str,
desc: str,
persona: str = "",
category: str = "",
recent_titles: Optional[list[str]] = None,
) -> str:
persona_extras = {
"enthusiastic_junior": "Be excited. Use **bold** for emphasis. Short excited sentences. End with a question sometimes.",
"grumpy_senior": "Be slightly cynical but helpful. Short blunt sentences. No fluff. Call out bad practices.",
"hobbyist_maker": "Be casual and friendly. Mention side projects and tinkering. Use *italics* for tools/libraries.",
"academic_type": "Be precise and structured. Use *italics* for terminology. Well thought out arguments.",
"storyteller": "Use **bold** for key points. Write anecdotal, narrative style. Longer flowing sentences.",
"rebel": "Be informal. Skip punctuation sometimes. Use slang. Type like you're in a hurry.",
"mentor": "Be helpful and explanatory. Use **bold** for key takeaways. Include practical advice.",
"minimalist": "One paragraph. Short blunt declarative sentences. No markdown. No fluff.",
}
category_extras = {
"devlog": "Write it as a personal devlog entry - share your learning process and insights about this topic.",
"showcase": "Write it as a showcase - express genuine excitement about what makes this impressive.",
"question": "Write it as a discussion starter - ask thoughtful questions, invite others to share perspectives.",
"rant": "Write it as an opinionated rant - strong viewpoint, passionate criticism, but keep it substantive.",
"fun": "Write it lighthearted and playful, but stay tied to the actual tech topic. Humor about the technology itself, not off-topic jokes or lyrics.",
"random": "Be natural and conversational - share your thoughts like any casual discussion.",
}
persona_extra = (
f" {persona_extras.get(persona, 'Be casual. No markdown.')}"
if persona
else " Be casual. No markdown."
)
category_extra = f" {category_extras.get(category, '')}" if category else ""
distinct_rule = ""
if recent_titles:
recent = "; ".join(t for t in recent_titles[-6:] if t)
if recent:
distinct_rule = (
f" You already posted about: {recent[:600]}. Take a completely "
"different angle from those and do not repeat their framing, "
"examples, or opinions."
)
preserve = persona in (
"enthusiastic_junior",
"hobbyist_maker",
"academic_type",
"storyteller",
"mentor",
)
text = self._call(
f"You are a dev writing a social media post reacting to tech news. Write 2-4 short paragraphs."
f"{persona_extra}{category_extra} Do not summarize the article; assume the reader already saw it. "
f"Add your own value: a concrete opinion, an implication, a personal experience, or a pointed question. "
f"Reference a specific detail rather than restating the headline. No em dashes. Under 300 words."
f"{distinct_rule}",
f"News: {title}\n\n{desc[:800]}",
)
return self.clean(text, preserve_md=preserve)
def generate_post_title(
self, headline: str, persona: str = "", category: str = ""
) -> str:
style = {
"enthusiastic_junior": "Sound excited and curious.",
"grumpy_senior": "Sound blunt and a little skeptical.",
"hobbyist_maker": "Sound casual and hands-on.",
"academic_type": "Sound precise and measured.",
"minimalist": "Keep it plain and very short.",
"storyteller": "Hint at a story or an angle.",
"rebel": "Sound provocative or contrarian.",
"mentor": "Sound thoughtful and constructive.",
}.get(persona, "")
title = self.strip_label(
self.clean(
self._call(
"You are a developer writing the title of a community forum post reacting to tech news. "
"Write a natural, human title of 3 to 8 words in your own voice. "
"Do not copy or paraphrase the full headline and do not restate every detail. "
"No trailing punctuation unless it is a genuine question. No quotes. No label prefix. "
f"No em dashes. {style}",
f"Headline: {headline}\nYour post title:",
temperature=0.8,
)
)
)
return title[:120]
def select_reaction(self, content_snippet: str, persona: str = "") -> str:
from devplacepy.constants import REACTION_EMOJI
flavor = {
"enthusiastic_junior": "You react readily and warmly.",
"grumpy_senior": "You react rarely, only to genuinely notable content.",
"hobbyist_maker": "You react to anything hands-on, clever, or fun.",
"academic_type": "You react only to substantive, rigorous content.",
"minimalist": "You react very sparingly.",
"storyteller": "You react to anything with a human angle.",
"rebel": "You react to bold or contrarian takes.",
"mentor": "You react supportively to effort and learning.",
}.get(persona, "")
options = " ".join(REACTION_EMOJI)
verdict = self._call(
"You are a developer browsing a community feed. Decide whether a post deserves an "
"emoji reaction and which single emoji best fits its content and sentiment. "
f"{flavor} Reply with EXACTLY one of these emojis: {options} "
"or the word NONE if the content is mundane or would not move you to react. "
"Output only the emoji or NONE, nothing else.",
f"Post:\n{content_snippet[:1200]}",
temperature=0.4,
)
text = verdict or ""
for emoji in REACTION_EMOJI:
if emoji in text or emoji.replace("\ufe0f", "") in text:
return emoji
return ""
@staticmethod
def pick_comment_style() -> str:
return random.choices(
["standard", "oneliner", "question"],
weights=[55, 23, 22],
k=1,
)[0]
@staticmethod
def is_short_comment_style(style: str) -> bool:
return style in ("oneliner", "question")
def generate_comment(
self,
post_snippet: str,
persona: str = "",
mention_target: str = "",
parent_context: str = "",
style: str = "",
existing_comments: str = "",
) -> str:
extras = {
"enthusiastic_junior": "Be excited. Use **bold** for agreement. Short replies.",
"grumpy_senior": "Be blunt and short. No markdown. One sarcastic remark or actual advice.",
"rebel": "Super casual. Skip caps sometimes. Short.",
"mentor": "Be helpful. Use **bold** for key point.",
"storyteller": "Share a quick related story. Use *italics* for emphasis.",
"minimalist": "Shortest possible reply. One sentence max.",
}
extra = (
f" {extras.get(persona, 'Be casual. No markdown.')}"
if persona
else " Be casual. No markdown."
)
preserve = persona in ("enthusiastic_junior", "mentor", "storyteller")
if style == "oneliner":
length_rule = (
"Write ONE short casual line, under 12 words, like a quick reply "
"you would type without thinking too hard. Lowercase is fine, "
"contractions are fine, no markdown."
)
preserve = False
elif style == "question":
length_rule = (
"Write a SINGLE pointed question about a specific detail in the post. "
"One sentence. No preamble."
)
else:
length_rule = f"Write 1-3 short sentences.{extra}"
mention_rule = ""
if mention_target:
mention_rule = (
f" Address @{mention_target} naturally in the first sentence "
f"(weave the @{mention_target} mention inline, do not append it at the end)."
)
ctx = ""
if parent_context:
ctx = f"\n\nReplying to this comment:\n{parent_context[:800]}"
others = ""
distinct_rule = ""
if existing_comments:
others = (
"\n\nComments already posted by others on this thread:\n"
f"{existing_comments[:1600]}"
)
distinct_rule = (
" Other people already commented (listed below). Contribute a point "
"none of them made: a different angle on the topic, a caveat they "
"missed, or respectful disagreement with one of them by name. Do not "
"repeat any opinion, framing, example, or question already raised."
)
system = (
f"You are a dev replying to a post. {length_rule}{mention_rule} "
"No em dashes. Reference a specific detail from the post. "
"Do not open with or rely on generic filler like 'great point', 'I agree', 'nice', "
"'thanks for sharing', or 'interesting'. Add something real: a concrete experience, "
"a caveat, a counterexample, respectful disagreement, or a pointed question. "
f"Never just paraphrase or agree blandly.{distinct_rule}"
)
reply = self.clean(
self._call(system, f"Post:\n{post_snippet[:1500]}{ctx}{others}").strip(),
preserve_md=preserve,
)
return reply[:2000]
@staticmethod
def _overlap_ratio(text: str, context: str) -> float:
def tokens(s: str) -> list[str]:
return [w for w in re.findall(r"[a-z0-9]+", s.lower()) if len(w) > 3]
candidate = tokens(text)
source = set(tokens(context))
if not candidate or not source:
return 0.0
hits = sum(1 for w in candidate if w in source)
return hits / len(candidate)
def quality_check(
self, kind: str, text: str, context: str = "", style: str = "", siblings: str = ""
) -> tuple[bool, str]:
from devplacepy.services.bot.config import (
MIN_COMMENT_LEN,
MIN_SHORT_COMMENT_LEN,
MIN_POST_LEN,
RESTATEMENT_OVERLAP_THRESHOLD,
SIBLING_OVERLAP_THRESHOLD,
GENERIC_COMMENT_PHRASES,
)
stripped = self.clean(text or "").strip()
if kind == "comment":
min_len = (
MIN_SHORT_COMMENT_LEN
if self.is_short_comment_style(style)
else MIN_COMMENT_LEN
)
else:
min_len = MIN_POST_LEN
if len(stripped) < min_len:
return False, f"too short ({len(stripped)} < {min_len})"
lowered = stripped.lower()
if kind == "comment":
for phrase in GENERIC_COMMENT_PHRASES:
if phrase in lowered:
return False, f"generic phrase '{phrase}'"
if (
context
and self._overlap_ratio(stripped, context) > RESTATEMENT_OVERLAP_THRESHOLD
):
return False, "restates the source"
if (
siblings
and self._overlap_ratio(stripped, siblings) > SIBLING_OVERLAP_THRESHOLD
):
return False, "echoes another comment"
verdict = self._call(
"You are a strict content quality reviewer for a developer community. "
"Reject text that is generic, low-effort, pure filler, or merely summarizes its "
"source without adding an opinion, experience, or insight. "
"Reply with exactly PASS or 'FAIL: <short reason>'.",
f"Type: {kind}\nText:\n{stripped[:1200]}",
temperature=0.0,
)
if verdict.strip().upper().startswith("PASS"):
return True, "ok"
return False, verdict.strip()[:120] or "judge rejected"
@staticmethod
def _parse_json(text: str) -> dict:
text = LLMClient.strip_code_fences(text or "").strip()
start = text.find("{")
end = text.rfind("}")
if start >= 0 and end > start:
text = text[start : end + 1]
parsed = json.loads(text)
if not isinstance(parsed, dict):
raise ValueError("expected a JSON object")
return parsed
@staticmethod
def _clamp01(value: Any, default: float) -> float:
try:
return max(0.0, min(1.0, float(value)))
except (TypeError, ValueError):
return default
@staticmethod
def _as_int(value: Any, default: int) -> int:
try:
return int(value)
except (TypeError, ValueError):
return default
@staticmethod
def _as_terms(value: Any) -> list[str]:
if isinstance(value, list):
return [str(item).strip() for item in value if str(item).strip()][:8]
if isinstance(value, str) and value.strip():
return [part.strip() for part in value.split(",") if part.strip()][:8]
return []
def _normalize_identity(self, data: dict, archetype: str) -> dict:
interests = self._as_terms(data.get("interests")) or list(
SEARCH_TERMS.get(archetype, [])
)
return {
"archetype": archetype,
"name": str(data.get("name", "")).strip()[:60],
"backstory": str(data.get("backstory", "")).strip()[:300],
"interests": interests,
"dislikes": self._as_terms(data.get("dislikes")),
"temperament": str(data.get("temperament", "")).strip()[:120],
"verbosity": self._clamp01(data.get("verbosity"), 0.5),
"contrarianness": self._clamp01(data.get("contrarianness"), 0.3),
"generosity": self._clamp01(data.get("generosity"), 0.5),
"curiosity": self._clamp01(data.get("curiosity"), 0.5),
"rhythm": str(data.get("rhythm", "")).strip()[:120],
}
def generate_identity(self, archetype: str) -> dict:
interests = ", ".join(SEARCH_TERMS.get(archetype, []))
system = (
"You invent a unique, believable individual developer for a social coding "
"platform, seeded from a broad archetype but distinct from anyone else who "
"shares it. Return ONLY a JSON object, no prose and no markdown fences, with "
"these keys: name (a short handle-like display name), backstory (one concrete "
"sentence), interests (array of 4 to 6 short topics), dislikes (array of 2 to 4 "
"short topics), temperament (a few words), verbosity (number 0.0 to 1.0), "
"contrarianness (number 0.0 to 1.0), generosity (number 0.0 to 1.0), curiosity "
"(number 0.0 to 1.0), rhythm (a few words on when and how they show up). Make it "
"specific and memorable, never generic. No em dashes."
)
prompt = (
f"Archetype: {archetype}\n"
f"Typical interests for this archetype: {interests}\n"
"Create the persona JSON:"
)
data = self._parse_json(self._raw_call(system, prompt, temperature=0.9))
return self._normalize_identity(data, archetype)
def generate_handle_candidates(self, archetype: str) -> list[str]:
interests = ", ".join(SEARCH_TERMS.get(archetype, []))
system = (
"You invent online handles for a developer signing up to a programmer "
"community in the style of devRant or Hacker News. The handles read like a "
"real nerd picked them, never like a person's full name. Lean on programming "
"and hacker culture: tech nouns (null, kernel, segfault, daemon), occasional "
"leetspeak (c0d3r, h4x), an adjective plus noun, a creature, or a short word "
f"with a number. Lowercase mostly, {MAX_HANDLE_LEN} characters or fewer, only "
"letters, digits, underscores and hyphens, no spaces and no dots. Return ONLY "
f'a JSON object {{"handles": ["...", "..."]}} with {HANDLE_CANDIDATE_TARGET} '
"distinct handles, no prose, no markdown fences. No em dashes."
)
prompt = (
f"Archetype: {archetype}\n"
f"Their interests: {interests}\n"
"Create the handles JSON:"
)
try:
data = self._parse_json(
self._raw_call(system, prompt, temperature=1.0)
)
except (ValueError, json.JSONDecodeError) as exc:
logger.warning("Handle candidate generation failed: %s", exc)
return []
handles: list[str] = []
for raw in data.get("handles", []):
handle = sanitize_handle(raw)
if handle and handle.lower() not in {h.lower() for h in handles}:
handles.append(handle)
return handles
@staticmethod
def _identity_card(identity: dict) -> str:
lines = [
f"name: {identity.get('name', '')}",
f"archetype: {identity.get('archetype', '')}",
f"backstory: {identity.get('backstory', '')}",
f"interests: {', '.join(identity.get('interests', []))}",
f"dislikes: {', '.join(identity.get('dislikes', []))}",
f"temperament: {identity.get('temperament', '')}",
f"verbosity: {identity.get('verbosity', 0.5)}",
f"contrarianness: {identity.get('contrarianness', 0.3)}",
f"generosity: {identity.get('generosity', 0.5)}",
f"curiosity: {identity.get('curiosity', 0.5)}",
f"rhythm: {identity.get('rhythm', '')}",
]
return "\n".join(lines)
def _decision_system(self, identity: dict) -> str:
return (
"You are role-playing a single developer on a social coding platform. Stay in "
"character at all times.\n\n"
"IDENTITY\n"
f"{self._identity_card(identity)}\n\n"
"HOW TO DECIDE\n"
"- Choose the actions that THIS person, with these interests and this "
"temperament, would take on the page described. Behaviour must follow the "
"identity, not chance.\n"
"- A generous person votes and reacts readily; a contrarian one comments to push "
"back; a terse, low-verbosity one acts rarely and briefly; a curious one explores "
"and navigates. Let the numbers and interests drive the plan.\n"
"- Only choose actions whose name appears in the MENU. Never invent an action or "
"a target.\n"
"- Order the plan the way this person would actually act, and include only what "
"they would genuinely do (an empty plan is fine if nothing here interests them).\n"
"- energy is how engaged this person is right now, 0.0 (barely present) to 1.0 "
"(highly active), following their rhythm.\n"
"- stop_after is roughly how many more actions this whole visit warrants before "
"they would naturally drift away.\n"
"- Output ONLY the JSON object below. No prose, no markdown fences.\n\n"
"OUTPUT SCHEMA\n"
'{"plan":[{"action":"<menu action>","target":"<id or empty>",'
'"rationale":"<short>"}],"energy":<0.0-1.0>,"stop_after":<integer>}'
)
@staticmethod
def _decision_prompt(page_state: dict, menu: list[dict], history: list[str]) -> str:
menu_lines = "\n".join(f"- {item['action']}: {item['desc']}" for item in menu)
recent = "; ".join(history[-8:]) if history else "nothing yet this visit"
unread = page_state.get("unread_notifications", 0)
unread_line = (
f"\nUNREAD NOTIFICATIONS: {unread} (someone may have mentioned or replied to you)"
if unread
else ""
)
return (
f"PAGE: {page_state.get('page', 'unknown')}\n"
f"VISIBLE: {page_state.get('visible', '')}{unread_line}\n"
f"MENU:\n{menu_lines}\n"
f"RECENT (this visit): {recent}"
)
@staticmethod
def _filter_plan(plan: Any, allowed: set) -> list[dict]:
if not isinstance(plan, list):
return []
result = []
for entry in plan:
if not isinstance(entry, dict):
continue
action = str(entry.get("action", "")).strip()
if action not in allowed:
continue
result.append(
{
"action": action,
"target": str(entry.get("target", "")).strip()[:120],
"rationale": str(entry.get("rationale", "")).strip()[:200],
}
)
return result[:12]
def decide(
self,
identity: dict,
page_state: dict,
menu: list[dict],
history: list[str],
temperature: float = 0.4,
) -> dict:
allowed = {item["action"] for item in menu}
system = self._decision_system(identity)
base = self._decision_prompt(page_state, menu, history)
result = {"plan": [], "energy": 0.5, "stop_after": 0}
for attempt in range(2):
prompt = base
if attempt:
prompt += "\n\nReturn ONLY valid JSON matching the schema. No prose."
try:
data = self._parse_json(self._raw_call(system, prompt, temperature))
except (ValueError, KeyError, json.JSONDecodeError):
continue
result = {
"plan": self._filter_plan(data.get("plan"), allowed),
"energy": self._clamp01(data.get("energy"), 0.5),
"stop_after": self._as_int(data.get("stop_after"), 0),
}
if result["plan"]:
break
return result
def generate_issue(self, topic: str) -> tuple[str, str]:
text = self._call(
"Write an issue report. One line title. Then 2-3 sentences describing what happened and what should have happened. Like a real dev reporting an issue. No em dashes.",
f"Issue: {topic}",
)
lines = text.strip().split("\n")
title = lines[0].strip().lstrip("#").strip()[:120] or f"Issue report: {topic}"
desc = " ".join(
line.lstrip("-* ").strip() for line in lines[1:] if line.strip()
)
return title, desc[:2000] or text[:500]
def generate_bio(self) -> str:
return self._call(
"Write a short bio for a developer profile. 1-2 sentences. What they work on, what they like. Sound human. No em dashes.",
"Bio:",
)
def generate_profile_fields(self, handle: str) -> tuple[str, str, str]:
location = self.clean(
self._call(
"Name one plausible city and country for a developer. Reply with ONLY 'City, Country'. No extra words.",
"Location:",
temperature=0.9,
)
)[:80]
slug = re.sub(r"[^a-z0-9_-]", "", handle.lower()) or "dev"
git_link = f"https://github.com/{slug}"
website = f"https://{slug}.dev"
return location, git_link, website
def generate_dm(self, persona: str = "", context: str = "") -> str:
extra = {
"enthusiastic_junior": "Be friendly and excited.",
"grumpy_senior": "Be blunt but not rude.",
"rebel": "Be super casual.",
"mentor": "Be warm and encouraging.",
"storyteller": "Open with a small hook.",
"minimalist": "One short sentence.",
}.get(persona, "Be casual and friendly.")
ctx = f"\n\nEarlier message:\n{context[:400]}" if context else ""
return self.clean(
self._call(
f"Write one short, friendly direct message to another developer. 1-2 sentences. {extra} No em dashes.",
f"Write a DM to start or continue a chat.{ctx}",
)
)[:500]
def generate_project_title(self, persona: str = "") -> str:
return self.strip_label(
self.clean(
self._call(
"Invent a short, catchy project name. 2 to 4 words. A tool, game, or app. "
"Output only the name. No label, no colon, no description, no quotes. No em dashes.",
"Project name:",
temperature=0.9,
)
)
)[:80]
def generate_project_desc(self, title: str, persona: str = "") -> str:
flavor = {
"grumpy_senior": "Keep it dry and matter of fact.",
"academic_type": "Be precise about the approach and trade-offs.",
"minimalist": "Two short sentences, no filler.",
"rebel": "Be bold about why the usual approach is wrong.",
"storyteller": "Open with the motivation behind it.",
}.get(persona, "")
shape = random.choice(
[
"Write one terse sentence. Just what it is. No tech stack.",
"Write two sentences: what it does and the main tech behind it.",
"Write 2 to 3 sentences including the tech stack and a trade-off you made.",
"Write a short blurb, under 25 words, plain and understated.",
]
)
return self.clean(
self._call(
f"You are a developer describing your own project. {shape} {flavor} No em dashes.",
f"Project: {title}",
)
)[:5000]
def generate_gist(self, persona: str = "") -> tuple[str, str, str, str]:
languages = PERSONA_LANGUAGES.get(persona) or GIST_LANGUAGES
language = random.choice(languages)
flavor = PERSONA_GIST_FLAVOR.get(persona, "a genuinely useful utility")
code = self.strip_code_fences(
self._call(
f"Write a short, correct, self-contained {language} snippet of 8 to 20 lines. "
f"It should be {flavor}. Make it non-trivial and genuinely useful: no hello world, "
"no bare language-feature demo, no textbook 101 example, no trivial one-liner, "
"no basic getter or setter. Output ONLY raw code. No markdown fences. No commentary.",
f"Language: {language}. Write the snippet:",
temperature=0.7,
)
)[:4000]
title = self.strip_label(
self.clean(
self._call(
"Name this code snippet in 2 to 5 words, like a developer titling a gist. "
"No quotes. No markdown. No label prefix. No em dashes.",
f"Language: {language}\nCode:\n{code[:1200]}\nTitle:",
temperature=0.7,
)
)
)[:120]
description = self.clean(
self._call(
"Write a one-sentence description of what this snippet does and when it is handy. No em dashes.",
f"Title: {title}\nLanguage: {language}\nCode:\n{code[:1200]}",
)
)[:400]
return title, description, language, code
def gist_quality_check(
self, title: str, code: str, language: str
) -> tuple[bool, str]:
lowered = (title or "").lower()
for term in TRIVIAL_GIST_TERMS:
if term in lowered:
return False, f"trivial topic '{term}'"
lines = [ln for ln in (code or "").splitlines() if ln.strip()]
if len(lines) < self.gist_min_lines:
return False, f"too few lines ({len(lines)} < {self.gist_min_lines})"
verdict = self._call(
"You are a strict reviewer for a developer community's shared code snippets. "
"Reject snippets that are textbook 101 material, trivial one-liners, hello world, "
"a bare language-feature demo, or something every developer already knows by heart. "
"Accept only snippets an experienced developer would find non-obvious or worth bookmarking. "
"Reply with exactly PASS or 'FAIL: <short reason>'.",
f"Language: {language}\nTitle: {title}\nCode:\n{code[:1500]}",
temperature=0.0,
)
if verdict.strip().upper().startswith("PASS"):
return True, "ok"
return False, verdict.strip()[:120] or "judge rejected"