Spaces:
Running
on
Zero
Running
on
Zero
import gradio as gr | |
import torch | |
from peft import PeftModel | |
from transformers import AutoModelForCausalLM, AutoTokenizer | |
import warnings | |
import traceback | |
import json | |
# Import spaces if available (for HuggingFace Spaces GPU optimization) | |
try: | |
import spaces | |
HAS_SPACES = True | |
except ImportError: | |
HAS_SPACES = False | |
warnings.filterwarnings('ignore') | |
# Global model variables | |
model = None | |
tokenizer = None | |
device = None | |
def load_model(): | |
"""Load the psychology-tuned model""" | |
global model, tokenizer, device | |
try: | |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
print(f"π Loading psychology model on {device}...") | |
# Load tokenizer | |
print("π Loading tokenizer...") | |
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") | |
if tokenizer.pad_token is None: | |
tokenizer.pad_token = tokenizer.eos_token | |
print("β Tokenizer loaded") | |
# Load base model | |
print("π§ Loading base model...") | |
base_model = AutoModelForCausalLM.from_pretrained( | |
"Qwen/Qwen2.5-0.5B", | |
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32, | |
device_map="auto" if torch.cuda.is_available() else None, | |
trust_remote_code=True | |
) | |
print("β Base model loaded") | |
# Load PEFT adapter | |
print("π§ Loading PEFT adapter...") | |
model = PeftModel.from_pretrained(base_model, "phxdev/psychology-qwen-0.5b") | |
model = model.merge_and_unload() | |
print("β PEFT adapter merged") | |
if not torch.cuda.is_available(): | |
model = model.to(device) | |
print("β Psychology model ready!") | |
return True | |
except Exception as e: | |
print(f"β Error loading model: {e}") | |
traceback.print_exc() | |
return False | |
def _generate_response(formatted_prompt: str, max_new_tokens: int = 200) -> str: | |
"""Core generation function optimized for friend-mode conversations""" | |
if model is None: | |
return "β οΈ Model not loaded. Please refresh and try again." | |
try: | |
inputs = tokenizer( | |
formatted_prompt, | |
return_tensors="pt", | |
truncation=True, | |
max_length=800 | |
).to(device) | |
# Friend-mode generation settings - conversational and supportive | |
with torch.no_grad(): | |
outputs = model.generate( | |
**inputs, | |
max_new_tokens=max_new_tokens, | |
temperature=0.7, # Balanced for natural conversation | |
top_p=0.9, | |
do_sample=True, | |
repetition_penalty=1.1, | |
pad_token_id=tokenizer.eos_token_id, | |
eos_token_id=tokenizer.eos_token_id, | |
) | |
full_response = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
generated_text = full_response[len(formatted_prompt):].strip() | |
# Clean up for natural conversation | |
if generated_text.startswith('"') and generated_text.endswith('"'): | |
generated_text = generated_text[1:-1] | |
stop_phrases = [ | |
"Their response", "Your response", "They said", "You said", | |
"And their response", "And your response", "Person:", "Response:" | |
] | |
for phrase in stop_phrases: | |
if phrase in generated_text: | |
generated_text = generated_text.split(phrase)[0].strip() | |
if not generated_text: | |
return "I'm here to help. Can you tell me more about what's going on?" | |
return generated_text | |
except Exception as e: | |
return f"β οΈ Generation error: {str(e)}" | |
# PRIMARY FRIEND MODE FUNCTIONS | |
def friend_support_internal(message: str) -> str: | |
"""Main friend support function - natural conversation""" | |
if not message.strip(): | |
return "Hey, what's on your mind?" | |
formatted_prompt = f"You're talking to a close friend who has psychology training. Your friend says: \"{message}\"\n\nAs their supportive friend, you respond:" | |
return _generate_response(formatted_prompt, max_new_tokens=180) | |
def friend_trauma_support_internal(message: str) -> str: | |
"""Friend helping with trauma - conversational support""" | |
if not message.strip(): | |
return "I'm here for you. What's been going on?" | |
formatted_prompt = f"Your friend who's been through trauma tells you: \"{message}\"\n\nAs someone who cares about them and has some psychology knowledge, you respond with understanding and support:" | |
return _generate_response(formatted_prompt, max_new_tokens=200) | |
def friend_emotional_support_internal(message: str) -> str: | |
"""Friend helping process emotions""" | |
if not message.strip(): | |
return "What are you feeling right now? I'm here to listen." | |
formatted_prompt = f"Your friend is struggling emotionally and tells you: \"{message}\"\n\nAs their friend who understands emotions, you help them process what they're going through:" | |
return _generate_response(formatted_prompt, max_new_tokens=170) | |
def friend_situation_analysis_internal(message: str) -> str: | |
"""Friend helping analyze a difficult situation""" | |
if not message.strip(): | |
return "Tell me what's happening. Let's figure this out together." | |
formatted_prompt = f"Your friend describes a difficult situation: \"{message}\"\n\nAs their friend who's good at seeing patterns and understanding people, you help them make sense of what's going on:" | |
return _generate_response(formatted_prompt, max_new_tokens=190) | |
def friend_relationship_help_internal(message: str) -> str: | |
"""Friend giving relationship perspective""" | |
if not message.strip(): | |
return "What's going on with your relationships? I'm here to help you think through it." | |
formatted_prompt = f"Your friend tells you about a relationship issue: \"{message}\"\n\nAs their friend who understands relationship dynamics, you offer perspective and support:" | |
return _generate_response(formatted_prompt, max_new_tokens=180) | |
def friend_coping_help_internal(situation: str) -> str: | |
"""Friend suggesting coping strategies""" | |
if not situation.strip(): | |
return "What are you dealing with? Let's brainstorm some ways to handle it." | |
formatted_prompt = f"Your friend is dealing with: \"{situation}\"\n\nAs their supportive friend with knowledge about coping strategies, you offer practical help:" | |
return _generate_response(formatted_prompt, max_new_tokens=200) | |
# STATIC SUPPORT RESOURCES | |
def crisis_resources_internal() -> str: | |
"""Get immediate crisis intervention resources""" | |
return """π **IMMEDIATE CRISIS RESOURCES** | |
**Emergency:** Call 911 or your local emergency number | |
**24/7 Crisis Support:** | |
β’ **988 Suicide & Crisis Lifeline**: Call or text 988 (US) | |
β’ **Crisis Text Line**: Text HOME to 741741 (US) | |
β’ **International**: https://iasp.info/resources/Crisis_Centres/ | |
**Specialized Support:** | |
β’ National Domestic Violence Hotline: 1-800-799-7233 | |
β’ SAMHSA National Helpline: 1-800-662-4357 | |
β’ Trans Lifeline: 877-565-8860 | |
β’ LGBT National Hotline: 1-888-843-4564 | |
β’ Veterans Crisis Line: 1-800-273-8255 | |
You are not alone. Help is available 24/7.""" | |
def mindfulness_exercise_internal() -> str: | |
"""Guided mindfulness exercise""" | |
return """π§ **5-MINUTE GROUNDING EXERCISE** | |
**Right now, notice:** | |
β’ **5 things you can SEE** (colors, shapes, objects) | |
β’ **4 things you can TOUCH** (chair, table, clothes, temperature) | |
β’ **3 things you can HEAR** (sounds around you) | |
β’ **2 things you can SMELL** (coffee, soap, air) | |
β’ **1 thing you can TASTE** (gum, coffee, or just your mouth) | |
**Box Breathing:** | |
β’ Inhale for 4 counts β Hold for 4 β Exhale for 4 β Hold for 4 | |
β’ Repeat 4-6 times | |
**Grounding Phrase:** "I am here. I am safe. This moment will pass." | |
You've got this. One breath at a time.""" | |
# BONUS BUSINESS ANALYSIS FUNCTIONS | |
def business_manipulation_analysis_internal(content: str) -> str: | |
"""Analyze business/marketing manipulation tactics - BONUS FEATURE""" | |
if not content.strip(): | |
return "Provide some marketing content or website copy to analyze." | |
formatted_prompt = f"As a friend with psychology knowledge, analyze what this business content is trying to do psychologically: \"{content}\"\n\nExplain the psychological tactics, manipulation techniques, and emotional triggers being used:" | |
return _generate_response(formatted_prompt, max_new_tokens=250) | |
def website_psychology_analysis_internal(content: str) -> str: | |
"""Analyze website psychological tactics - BONUS FEATURE""" | |
if not content.strip(): | |
return "Describe the website content or user experience to analyze." | |
formatted_prompt = f"As a friend who understands web psychology, help me understand what's happening with this website experience: \"{content}\"\n\nWhat psychological techniques are they using? How should someone protect themselves?" | |
return _generate_response(formatted_prompt, max_new_tokens=280) | |
def competitive_psychology_analysis_internal(content: str) -> str: | |
"""Analyze competitor psychological tactics - BONUS FEATURE""" | |
if not content.strip(): | |
return "Describe the competitor's content or approach to analyze." | |
formatted_prompt = f"As a friend helping with business strategy, analyze the psychological approach in this competitor content: \"{content}\"\n\nWhat persuasion techniques are they using? What cognitive biases are they exploiting? How effective is this approach?" | |
return _generate_response(formatted_prompt, max_new_tokens=300) | |
def psychology_mcp_router(function_name: str, parameters: str) -> str: | |
""" | |
Friend-Mode Psychology Router with Business Analysis Bonus | |
Args: | |
function_name (str): Function to call | |
parameters (str): JSON string with function parameters | |
Returns: | |
str: Response from the psychology-informed friend system | |
""" | |
try: | |
# Parse parameters if provided | |
if parameters.strip(): | |
params = json.loads(parameters) | |
else: | |
params = {} | |
# PRIMARY FRIEND MODE FUNCTIONS | |
if function_name == "friend_support": | |
return friend_support_internal(params.get("message", "")) | |
elif function_name == "friend_trauma_support": | |
return friend_trauma_support_internal(params.get("message", "")) | |
elif function_name == "friend_emotional_support": | |
return friend_emotional_support_internal(params.get("message", "")) | |
elif function_name == "friend_situation_analysis": | |
return friend_situation_analysis_internal(params.get("message", "")) | |
elif function_name == "friend_relationship_help": | |
return friend_relationship_help_internal(params.get("message", "")) | |
elif function_name == "friend_coping_help": | |
return friend_coping_help_internal(params.get("situation", "")) | |
elif function_name == "crisis_resources": | |
return crisis_resources_internal() | |
elif function_name == "mindfulness_exercise": | |
return mindfulness_exercise_internal() | |
# BONUS BUSINESS ANALYSIS FUNCTIONS | |
elif function_name == "business_manipulation_analysis": | |
return business_manipulation_analysis_internal(params.get("content", "")) | |
elif function_name == "website_psychology_analysis": | |
return website_psychology_analysis_internal(params.get("content", "")) | |
elif function_name == "competitive_psychology_analysis": | |
return competitive_psychology_analysis_internal(params.get("content", "")) | |
elif function_name == "list_functions": | |
return json.dumps({ | |
"primary_friend_functions": { | |
"functions": [ | |
"friend_support", "friend_trauma_support", "friend_emotional_support", | |
"friend_situation_analysis", "friend_relationship_help", "friend_coping_help", | |
"crisis_resources", "mindfulness_exercise" | |
], | |
"parameters": {"message": "text"} or {"situation": "text"}, | |
"purpose": "Psychology-informed friend for personal support and understanding" | |
}, | |
"bonus_business_functions": { | |
"functions": [ | |
"business_manipulation_analysis", "website_psychology_analysis", | |
"competitive_psychology_analysis" | |
], | |
"parameters": {"content": "text"}, | |
"purpose": "Analyze business/marketing psychological tactics (bonus feature)" | |
}, | |
"usage_examples": { | |
"friend_mode": '{"message": "I feel overwhelmed by online shopping pressure"}', | |
"business_bonus": '{"content": "Buy now! Limited time offer! Only 3 left!"}' | |
} | |
}) | |
else: | |
return json.dumps({ | |
"error": f"Unknown function: {function_name}", | |
"primary_functions": [ | |
"friend_support", "friend_trauma_support", "friend_emotional_support", | |
"friend_situation_analysis", "friend_relationship_help", "friend_coping_help", | |
"crisis_resources", "mindfulness_exercise" | |
], | |
"bonus_functions": [ | |
"business_manipulation_analysis", "website_psychology_analysis", | |
"competitive_psychology_analysis" | |
] | |
}) | |
except json.JSONDecodeError: | |
return json.dumps({ | |
"error": "Invalid JSON in parameters", | |
"friend_example": '{"message": "your situation here"}', | |
"business_example": '{"content": "marketing content to analyze"}' | |
}) | |
except Exception as e: | |
return json.dumps({ | |
"error": f"Friend psychology system error: {str(e)}" | |
}) | |
# Apply GPU optimization if available | |
if HAS_SPACES: | |
psychology_mcp_router = spaces.GPU(psychology_mcp_router) | |
# Initialize model | |
print("π Starting Psychology-Informed Friend Agent...") | |
model_loaded = load_model() | |
if model_loaded: | |
print("β Creating friend-mode MCP interface...") | |
# Create the friend-focused MCP interface | |
demo = gr.Interface( | |
fn=psychology_mcp_router, | |
inputs=[ | |
gr.Textbox( | |
label="Function Name", | |
placeholder="friend_support", | |
info="FRIEND MODE: friend_support, friend_trauma_support, friend_emotional_support, friend_situation_analysis, friend_relationship_help, friend_coping_help | BONUS: business_manipulation_analysis, website_psychology_analysis" | |
), | |
gr.Textbox( | |
label="Parameters (JSON)", | |
placeholder='{"message": "I feel overwhelmed by shopping websites"}', | |
lines=4, | |
info='Friend Mode: {"message": "what\'s happening"} | Business Bonus: {"content": "marketing content to analyze"}' | |
) | |
], | |
outputs=gr.Textbox( | |
label="Friend Response", | |
lines=12 | |
), | |
title="π€ Psychology-Informed Friend - Personal Support + Business Insights", | |
description="""**β οΈ SAFETY NOTICE: This is NOT medical advice. For crisis situations, call 911 or 988.** | |
*This model may not be perfect, it may be clinical when we need a friend. But the alternative is silence. And that helps no one.* | |
**PRIMARY PURPOSE: Your Psychology-Informed Friend** | |
A supportive friend with psychology training who helps you understand what's happening in your life, process emotions, and navigate difficult situations. | |
**BONUS FEATURE: Business Psychology Analysis** | |
Also happens to be great at analyzing marketing manipulation, website psychology tactics, and competitive persuasion techniques. | |
**How to use**: Talk to it like a friend who understands psychology. Frame your questions conversationally.""", | |
examples=[ | |
["friend_support", '{"message": "I feel manipulated by shopping websites with their countdown timers"}'], | |
["friend_trauma_support", '{"message": "I have PTSD from medical situations and need someone to understand"}'], | |
["friend_emotional_support", '{"message": "I feel angry and helpless about things I cannot control"}'], | |
["friend_situation_analysis", '{"message": "I keep getting pressured by sales tactics and want to understand why"}'], | |
["business_manipulation_analysis", '{"content": "Try Walmart+ for FREE! Order within 11 hr 59 min. Only 5 left!"}'], | |
["website_psychology_analysis", '{"content": "Countdown timers, scarcity messages, and subscription pressure at checkout"}'], | |
["crisis_resources", "{}"], | |
["list_functions", "{}"] | |
] | |
) | |
if __name__ == "__main__": | |
demo.launch( | |
share=True, | |
server_name="0.0.0.0", | |
server_port=7860, | |
show_error=True, | |
mcp_server=True | |
) | |
else: | |
print("β Failed to load psychology model") | |
def error_response(function_name, parameters): | |
return "β οΈ Model loading error. Please check console logs and try restarting." | |
demo = gr.Interface( | |
fn=error_response, | |
inputs=["text", "text"], | |
outputs="text", | |
title="β οΈ Personal Agent - Loading Error" | |
) | |
if __name__ == "__main__": | |
demo.launch(share=True, mcp_server=True) |