""" connectd - groq message drafting reads soul from file, uses as guideline for llm to personalize """ import os import json from groq import Groq GROQ_API_KEY = os.getenv("GROQ_API_KEY") GROQ_MODEL = os.getenv("GROQ_MODEL", "llama-3.3-70b-versatile") client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None # load soul from file (guideline, not script) SOUL_PATH = os.getenv("SOUL_PATH", "/app/soul.txt") def load_soul(): try: with open(SOUL_PATH, 'r') as f: return f.read().strip() except: return None SIGNATURE_HTML = """
github.com/sudoxnym/connectd (main repo)
""" SIGNATURE_PLAINTEXT = """ --- github.com/sudoxnym/connectd (main repo) github: github.com/connectd-daemon mastodon: @connectd@mastodon.sudoxreboot.com bluesky: connectd.bsky.social lemmy: lemmy.sudoxreboot.com/c/connectd discord: discord.gg/connectd matrix: @connectd:sudoxreboot.com reddit: reddit.com/r/connectd email: connectd@sudoxreboot.com """ def draft_intro_with_llm(match_data: dict, recipient: str = 'a', dry_run: bool = True): """ draft an intro message using groq llm. args: match_data: dict with human_a, human_b, overlap_score, overlap_reasons recipient: 'a' or 'b' - who receives the message dry_run: if True, preview mode returns: tuple (result_dict, error_string) result_dict has: subject, draft_html, draft_plain """ if not client: return None, "GROQ_API_KEY not set" try: human_a = match_data.get('human_a', {}) human_b = match_data.get('human_b', {}) reasons = match_data.get('overlap_reasons', []) # recipient gets the message, about_person is who we're introducing them to if recipient == 'a': to_person = human_a about_person = human_b else: to_person = human_b about_person = human_a to_name = to_person.get('username', 'friend') about_name = about_person.get('username', 'someone') about_bio = about_person.get('extra', {}).get('bio', '') # format the shared factors naturally if reasons: factor = ', '.join(reasons[:3]) if len(reasons) > 1 else reasons[0] else: factor = "shared values and interests" # load soul as guideline soul = load_soul() if not soul: return None, "could not load soul file" # build the prompt - soul is GUIDELINE not script prompt = f"""you are connectd, a daemon that finds isolated builders and connects them. write a personal message TO {to_name} telling them about {about_name}. here is the soul/spirit of what connectd is about - use this as a GUIDELINE for tone and message, NOT as a script to copy verbatim: --- {soul} --- key facts for this message: - recipient: {to_name} - introducing them to: {about_name} - their shared interests/values: {factor} - about {about_name}: {about_bio if about_bio else 'a builder like you'} CRITICAL RULES - DO NOT SANITIZE: 1. use their name ({to_name}) throughout - make it personal 2. format the shared factor naturally like "your shared interest in X and Y" or "your work on X" 3. this message is TO {to_name} ABOUT {about_name} - don't confuse this 4. keep it lowercase, raw, emotional, real 5. no corporate speak, no "best regards", no "hi there" 6. DO NOT water down the message - keep the raw emotional energy 7. address them directly, call them to action 8. make them feel seen and not alone 9. end with rallying energy about building together return ONLY the message body. signature is added separately.""" response = client.chat.completions.create( model=GROQ_MODEL, messages=[{"role": "user", "content": prompt}], temperature=0.8, max_tokens=1200 ) body = response.choices[0].message.content.strip() # generate subject subject_prompt = f"""generate a short, lowercase email subject for a message to {to_name} about connecting them with {about_name} over their shared interest in {factor}. no corporate speak. no clickbait. raw and real. examples: - "found you, {to_name}" - "you're not alone" - "a door just opened" - "{to_name}, there's someone you should meet" return ONLY the subject line.""" subject_response = client.chat.completions.create( model=GROQ_MODEL, messages=[{"role": "user", "content": subject_prompt}], temperature=0.9, max_tokens=50 ) subject = subject_response.choices[0].message.content.strip().strip('"').strip("'") # format html draft_html = f"
{body}
{SIGNATURE_HTML}" draft_plain = body + SIGNATURE_PLAINTEXT return { 'subject': subject, 'draft_html': draft_html, 'draft_plain': draft_plain }, None except Exception as e: return None, str(e) # for backwards compat with old code def draft_message(person: dict, factor: str, platform: str = "email") -> dict: """legacy function - wraps new api""" match_data = { 'human_a': {'username': 'recipient'}, 'human_b': person, 'overlap_reasons': [factor] } result, error = draft_intro_with_llm(match_data, recipient='a') if error: raise ValueError(error) return { 'subject': result['subject'], 'body_html': result['draft_html'], 'body_plain': result['draft_plain'] } if __name__ == "__main__": # test test_data = { 'human_a': {'username': 'sudoxnym', 'extra': {'bio': 'building intentional communities'}}, 'human_b': {'username': 'testuser', 'extra': {'bio': 'home assistant enthusiast'}}, 'overlap_reasons': ['home-assistant', 'open source', 'community building'] } result, error = draft_intro_with_llm(test_data, recipient='a') if error: print(f"error: {error}") else: print(f"subject: {result['subject']}") print(f"\nbody:\n{result['draft_plain']}")