natgluons commited on
Commit
99ec0c6
Β·
0 Parent(s):

Initial commit

Browse files
.gitignore ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual Environment
24
+ venv/
25
+ env/
26
+ ENV/
27
+ .env
28
+
29
+ # IDE
30
+ .idea/
31
+ .vscode/
32
+ *.swp
33
+ *.swo
34
+
35
+ # OS
36
+ .DS_Store
37
+ Thumbs.db
38
+
39
+ # Model files and cache
40
+ .cache/
41
+ models/
42
+ *.bin
43
+ *.pt
44
+ *.pth
45
+ *.onnx
46
+ *.h5
47
+ *.hdf5
48
+
49
+ # Logs
50
+ *.log
51
+ logs/
52
+
53
+ # Gradio
54
+ flagged/
55
+
56
+ # Next.js
57
+ .next/
58
+ out/
59
+ build/
60
+ dist/
61
+ .env*.local
62
+ .env.development.local
63
+ .env.test.local
64
+ .env.production.local
pickup-line-generator/.gitignore ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dependencies
2
+ /node_modules
3
+ /.pnp
4
+ .pnp.js
5
+
6
+ # testing
7
+ /coverage
8
+
9
+ # next.js
10
+ /.next/
11
+ /out/
12
+
13
+ # production
14
+ /build
15
+
16
+ # misc
17
+ .DS_Store
18
+ *.pem
19
+
20
+ # debug
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
24
+
25
+ # local env files
26
+ .env*.local
27
+ .env
28
+
29
+ # vercel
30
+ .vercel
31
+
32
+ # typescript
33
+ *.tsbuildinfo
34
+ next-env.d.ts
35
+
36
+ # IDE specific files
37
+ .idea
38
+ .vscode
39
+ *.swp
40
+ *.swo
41
+
42
+ # OS generated files
43
+ .DS_Store
44
+ .DS_Store?
45
+ ._*
46
+ .Spotlight-V100
47
+ .Trashes
48
+ ehthumbs.db
49
+ Thumbs.db
50
+
51
+ # Python virtual environment (if you're using Python for the model)
52
+ venv/
53
+ env/
54
+ ENV/
55
+
56
+ # Model files and cache
57
+ .cache/
58
+ models/
59
+ *.bin
60
+ *.pt
61
+ *.pth
62
+ *.onnx
63
+ *.h5
64
+ *.hdf5
65
+
66
+ # Logs
67
+ logs
68
+ *.log
69
+
70
+ # Optional npm cache directory
71
+ .npm
72
+
73
+ # Optional eslint cache
74
+ .eslintcache
75
+
76
+ # Optional REPL history
77
+ .node_repl_history
78
+
79
+ # Output of 'npm pack'
80
+ *.tgz
81
+
82
+ # Yarn Integrity file
83
+ .yarn-integrity
84
+
85
+ # dotenv environment variable files
86
+ .env.development.local
87
+ .env.test.local
88
+ .env.production.local
pickup-line-generator/app/api/generate/route.ts ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextResponse } from 'next/server';
2
+ import { getVibeGuidance } from '@/lib/prompts';
3
+
4
+ export async function POST(request: Request) {
5
+ // Handle CORS
6
+ if (request.method === 'OPTIONS') {
7
+ return new NextResponse(null, {
8
+ status: 200,
9
+ headers: {
10
+ 'Access-Control-Allow-Origin': '*',
11
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
12
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
13
+ },
14
+ });
15
+ }
16
+
17
+ try {
18
+ const { vibe } = await request.json();
19
+
20
+ // Get the vibe guidance
21
+ const vibeGuide = getVibeGuidance(vibe);
22
+
23
+ // Create the prompt
24
+ const prompt = `Instructions: Generate a pickup line with a ${vibe} vibe.\n${vibeGuide}`;
25
+
26
+ // TODO: Replace this with actual model inference
27
+ // For now, return a mock response
28
+ const mockResponses = {
29
+ romantic: "Are you a magician? Because whenever I look at you, everyone else disappears. ❀️",
30
+ cheesy: "Are you a parking ticket? Because you've got FINE written all over you! 😏",
31
+ nerdy: "Are you made of copper and tellurium? Because you're Cu-Te! πŸ”¬",
32
+ cringe: "Are you a dictionary? Because you're adding meaning to my life! πŸ“š",
33
+ flirty: "Is your name Google? Because you've got everything I've been searching for! 😏"
34
+ };
35
+
36
+ const response = NextResponse.json({ pickupLine: mockResponses[vibe as keyof typeof mockResponses] });
37
+
38
+ // Add CORS headers to the response
39
+ response.headers.set('Access-Control-Allow-Origin', '*');
40
+ response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
41
+ response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
42
+
43
+ return response;
44
+ } catch (error) {
45
+ console.error('Error generating pickup line:', error);
46
+ const errorResponse = NextResponse.json(
47
+ { error: 'Failed to generate pickup line' },
48
+ { status: 500 }
49
+ );
50
+
51
+ // Add CORS headers to the error response
52
+ errorResponse.headers.set('Access-Control-Allow-Origin', '*');
53
+ errorResponse.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
54
+ errorResponse.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
55
+
56
+ return errorResponse;
57
+ }
58
+ }
pickup-line-generator/app/globals.css ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ :root {
6
+ --foreground-rgb: 0, 0, 0;
7
+ --background-start-rgb: 254, 246, 249;
8
+ --background-end-rgb: 255, 255, 255;
9
+ }
10
+
11
+ body {
12
+ color: rgb(var(--foreground-rgb));
13
+ background: rgb(var(--background-start-rgb));
14
+ }
pickup-line-generator/app/layout.tsx ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Metadata } from 'next';
2
+ import { Inter, Lobster } from 'next/font/google';
3
+ import { Toaster } from 'react-hot-toast';
4
+ import './globals.css';
5
+
6
+ const inter = Inter({ subsets: ['latin'], variable: '--font-inter' });
7
+ const lobster = Lobster({
8
+ weight: '400',
9
+ subsets: ['latin'],
10
+ variable: '--font-lobster',
11
+ });
12
+
13
+ export const metadata: Metadata = {
14
+ title: 'Pickup Line Generator',
15
+ description: 'Generate fun, clever, or cringey pickup lines using SmolLM!',
16
+ };
17
+
18
+ export default function RootLayout({
19
+ children,
20
+ }: {
21
+ children: React.ReactNode;
22
+ }) {
23
+ return (
24
+ <html lang="en">
25
+ <body className={`${inter.variable} ${lobster.variable} font-sans`}>
26
+ {children}
27
+ <Toaster position="bottom-center" />
28
+ </body>
29
+ </html>
30
+ );
31
+ }
pickup-line-generator/app/page.tsx ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { toast } from 'react-hot-toast';
5
+
6
+ const vibes = [
7
+ { id: 'romantic', label: 'πŸ’ Romantic', emoji: '❀️' },
8
+ { id: 'cheesy', label: 'πŸ§€ Cheesy', emoji: '😏' },
9
+ { id: 'nerdy', label: 'πŸ€“ Nerdy', emoji: 'πŸ”¬' },
10
+ { id: 'cringe', label: '😬 Cringe', emoji: 'πŸ˜‚' },
11
+ { id: 'flirty', label: '😘 Flirty', emoji: 'πŸ’‹' },
12
+ ];
13
+
14
+ export default function Home() {
15
+ const [selectedVibe, setSelectedVibe] = useState(vibes[0].id);
16
+ const [pickupLine, setPickupLine] = useState('');
17
+ const [isLoading, setIsLoading] = useState(false);
18
+
19
+ const generatePickupLine = async () => {
20
+ setIsLoading(true);
21
+ try {
22
+ const response = await fetch('/api/generate', {
23
+ method: 'POST',
24
+ headers: {
25
+ 'Content-Type': 'application/json',
26
+ },
27
+ body: JSON.stringify({ vibe: selectedVibe }),
28
+ });
29
+
30
+ if (!response.ok) throw new Error('Failed to generate pickup line');
31
+
32
+ const data = await response.json();
33
+ setPickupLine(data.pickupLine);
34
+ } catch (error) {
35
+ toast.error('Failed to generate pickup line');
36
+ console.error(error);
37
+ } finally {
38
+ setIsLoading(false);
39
+ }
40
+ };
41
+
42
+ const copyToClipboard = async () => {
43
+ try {
44
+ await navigator.clipboard.writeText(pickupLine);
45
+ toast.success('Copied to clipboard!');
46
+ } catch (error) {
47
+ toast.error('Failed to copy');
48
+ }
49
+ };
50
+
51
+ return (
52
+ <main className="min-h-screen bg-pink-50 py-12 px-4 sm:px-6 lg:px-8">
53
+ <div className="max-w-2xl mx-auto">
54
+ <div className="text-center mb-12">
55
+ <h1 className="text-4xl font-display font-bold text-pink-600 mb-4">
56
+ πŸ’˜ Pickup Line Generator
57
+ </h1>
58
+ <p className="text-gray-600">
59
+ Generate fun, clever, or cringey pickup lines using SmolLM! Select a vibe and click generate to get started! 😏
60
+ </p>
61
+ </div>
62
+
63
+ <div className="bg-white rounded-2xl shadow-xl p-8 space-y-6">
64
+ <div className="space-y-4">
65
+ <label htmlFor="vibe" className="block text-sm font-medium text-gray-700">
66
+ Choose a vibe
67
+ </label>
68
+ <select
69
+ id="vibe"
70
+ value={selectedVibe}
71
+ onChange={(e) => setSelectedVibe(e.target.value)}
72
+ className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-pink-500 focus:border-pink-500 sm:text-sm rounded-md"
73
+ >
74
+ {vibes.map((vibe) => (
75
+ <option key={vibe.id} value={vibe.id}>
76
+ {vibe.label}
77
+ </option>
78
+ ))}
79
+ </select>
80
+ </div>
81
+
82
+ <button
83
+ onClick={generatePickupLine}
84
+ disabled={isLoading}
85
+ className="w-full bg-gradient-to-r from-pink-500 to-pink-600 text-white py-3 px-4 rounded-lg font-medium hover:from-pink-600 hover:to-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 transition-all duration-200 shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-not-allowed"
86
+ >
87
+ {isLoading ? 'Generating...' : 'Generate Line'}
88
+ </button>
89
+
90
+ {pickupLine && (
91
+ <div className="space-y-4">
92
+ <div className="bg-pink-50 rounded-lg p-4">
93
+ <p className="text-gray-800 text-lg">{pickupLine}</p>
94
+ </div>
95
+
96
+ <div className="flex space-x-4">
97
+ <button
98
+ onClick={generatePickupLine}
99
+ className="flex-1 bg-white border border-pink-500 text-pink-500 py-2 px-4 rounded-lg font-medium hover:bg-pink-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 transition-all duration-200"
100
+ >
101
+ πŸ” Generate Again
102
+ </button>
103
+ <button
104
+ onClick={copyToClipboard}
105
+ className="flex-1 bg-white border border-pink-500 text-pink-500 py-2 px-4 rounded-lg font-medium hover:bg-pink-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 transition-all duration-200"
106
+ >
107
+ πŸ“‹ Copy
108
+ </button>
109
+ </div>
110
+ </div>
111
+ )}
112
+ </div>
113
+
114
+ <div className="mt-8 text-center text-gray-500">
115
+ Built by Nath with SmolLM πŸ”₯
116
+ </div>
117
+ </div>
118
+ </main>
119
+ );
120
+ }
pickup-line-generator/next.config.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ swcMinify: true,
5
+ }
6
+
7
+ module.exports = nextConfig
pickup-line-generator/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
pickup-line-generator/package.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "pickup-line-generator",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "next": "14.1.0",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0",
15
+ "react-hot-toast": "^2.4.1"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "20.17.27",
19
+ "@types/react": "18.3.20",
20
+ "@types/react-dom": "^18.2.19",
21
+ "autoprefixer": "^10.4.17",
22
+ "eslint": "^8.56.0",
23
+ "eslint-config-next": "14.1.0",
24
+ "postcss": "^8.4.35",
25
+ "tailwindcss": "^3.4.1",
26
+ "typescript": "5.8.2"
27
+ }
28
+ }
pickup-line-generator/postcss.config.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
pickup-line-generator/tailwind.config.ts ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Config } from 'tailwindcss';
2
+
3
+ const config: Config = {
4
+ content: [
5
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
6
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
7
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
8
+ ],
9
+ theme: {
10
+ extend: {
11
+ fontFamily: {
12
+ sans: ['var(--font-inter)'],
13
+ display: ['var(--font-lobster)'],
14
+ },
15
+ colors: {
16
+ pink: {
17
+ 50: '#fef6f9',
18
+ 500: '#ff69b4',
19
+ 600: '#ff1493',
20
+ 700: '#db2777',
21
+ },
22
+ },
23
+ },
24
+ },
25
+ plugins: [],
26
+ };
27
+
28
+ export default config;
pickup-line-generator/tsconfig.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
+ "exclude": ["node_modules"]
27
+ }
pickup-line-generator/vercel.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": 2,
3
+ "builds": [
4
+ {
5
+ "src": "package.json",
6
+ "use": "@vercel/next"
7
+ }
8
+ ],
9
+ "routes": [
10
+ {
11
+ "src": "/(.*)",
12
+ "dest": "/"
13
+ }
14
+ ],
15
+ "env": {
16
+ "NEXT_PUBLIC_API_URL": "https://your-vercel-domain.vercel.app/api"
17
+ }
18
+ }
smollm_web_pickuplinegenerator.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import AutoModelForCausalLM, AutoTokenizer
3
+ import gradio as gr
4
+ import re
5
+
6
+ # Set page title and description
7
+ title = "πŸ’– Pickup Line Generator"
8
+ description = """
9
+ <div style="text-align: center; max-width: 650px; margin: 0 auto;">
10
+ <div>
11
+ <p>Generate fun, clever, or cringey pickup lines using SmolLM-135M! Select a vibe and click generate to get started! 😏</p>
12
+ </div>
13
+ </div>
14
+ """
15
+
16
+ # Load model and tokenizer
17
+ print("Loading SmolLM-135M model...")
18
+ MODEL_NAME = "HuggingFaceTB/SmolLM-135M"
19
+
20
+ # Check for CUDA availability
21
+ device = "cuda" if torch.cuda.is_available() else "cpu"
22
+ print(f"Using device: {device}")
23
+
24
+ # Load the model and tokenizer
25
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
26
+ # Set pad_token to eos_token to handle padding
27
+ tokenizer.pad_token = tokenizer.eos_token
28
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to(device)
29
+
30
+ print(f"Model loaded successfully! Memory footprint: {model.get_memory_footprint() / 1e6:.2f} MB")
31
+
32
+ def get_vibe_guidance(vibe):
33
+ """Get specific guidance for each vibe with examples"""
34
+ vibe_patterns = {
35
+ "romantic": """Generate a romantic and sweet pickup line that's genuine and heartfelt.
36
+ Example:
37
+ Input: Generate a romantic pickup line
38
+ Output: Are you a magician? Because whenever I look at you, everyone else disappears. ❀️
39
+
40
+ Now generate a romantic pickup line: """,
41
+
42
+ "cheesy": """Generate a super cheesy and over-the-top pickup line.
43
+ Example:
44
+ Input: Generate a cheesy pickup line
45
+ Output: Are you a parking ticket? Because you've got FINE written all over you! 😏
46
+
47
+ Now generate a cheesy pickup line: """,
48
+
49
+ "nerdy": """Generate a nerdy, science-themed pickup line.
50
+ Example:
51
+ Input: Generate a nerdy pickup line
52
+ Output: Are you made of copper and tellurium? Because you're Cu-Te! πŸ”¬
53
+
54
+ Now generate a nerdy pickup line: """,
55
+
56
+ "cringe": """Generate the most cringey and over-the-top pickup line imaginable.
57
+ Example:
58
+ Input: Generate a cringe pickup line
59
+ Output: Are you a dictionary? Because you're adding meaning to my life! πŸ“š
60
+
61
+ Now generate a cringe pickup line: """,
62
+
63
+ "flirty": """Generate a bold and flirty pickup line.
64
+ Example:
65
+ Input: Generate a flirty pickup line
66
+ Output: Is your name Google? Because you've got everything I've been searching for! 😏
67
+
68
+ Now generate a flirty pickup line: """
69
+ }
70
+ return vibe_patterns.get(vibe, "Generate a pickup line with a ")
71
+
72
+ def generate_pickup_line(vibe):
73
+ """Generate a pickup line based on the selected vibe"""
74
+ # Get the vibe guidance
75
+ vibe_guide = get_vibe_guidance(vibe)
76
+
77
+ # Create the prompt
78
+ prompt = f"""Instructions: Generate a pickup line with a {vibe} vibe.
79
+ {vibe_guide}"""
80
+
81
+ # Prepare inputs with explicit attention mask
82
+ encoded_input = tokenizer.encode_plus(
83
+ prompt,
84
+ return_tensors="pt",
85
+ padding=True,
86
+ return_attention_mask=True
87
+ )
88
+ input_ids = encoded_input["input_ids"].to(device)
89
+ attention_mask = encoded_input["attention_mask"].to(device)
90
+
91
+ # Generate multiple responses and pick the best one
92
+ num_tries = 3
93
+ best_response = None
94
+
95
+ for _ in range(num_tries):
96
+ with torch.no_grad():
97
+ outputs = model.generate(
98
+ input_ids,
99
+ attention_mask=attention_mask,
100
+ max_new_tokens=100,
101
+ do_sample=True,
102
+ temperature=0.8,
103
+ top_p=0.92,
104
+ top_k=50,
105
+ pad_token_id=tokenizer.eos_token_id,
106
+ eos_token_id=tokenizer.eos_token_id,
107
+ )
108
+
109
+ # Get the full generated text
110
+ full_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
111
+
112
+ # Extract just the pickup line
113
+ if full_response.startswith(prompt):
114
+ response = full_response[len(prompt):].strip()
115
+ else:
116
+ response = full_response.replace(prompt, "").strip()
117
+
118
+ # Clean up the response
119
+ for marker in ["Instructions:", "Generate a pickup line:", "\n"]:
120
+ if marker in response:
121
+ response = response.split(marker, 1)[0].strip()
122
+
123
+ # Add appropriate emoji based on vibe
124
+ if vibe == "romantic":
125
+ response += " ❀️"
126
+ elif vibe == "cheesy":
127
+ response += " 😏"
128
+ elif vibe == "nerdy":
129
+ response += " πŸ”¬"
130
+ elif vibe == "cringe":
131
+ response += " πŸ˜‚"
132
+ elif vibe == "flirty":
133
+ response += " πŸ’‹"
134
+
135
+ best_response = response
136
+ break
137
+
138
+ return best_response
139
+
140
+ # Create custom CSS
141
+ custom_css = """
142
+ .gradio-container {
143
+ background-color: #fef6f9 !important;
144
+ }
145
+ .title {
146
+ font-family: 'Lobster', cursive !important;
147
+ color: #ff69b4 !important;
148
+ }
149
+ .button {
150
+ background: linear-gradient(45deg, #ff69b4, #ff1493) !important;
151
+ color: white !important;
152
+ border: none !important;
153
+ transition: all 0.3s ease !important;
154
+ }
155
+ .button:hover {
156
+ transform: translateY(-2px);
157
+ box-shadow: 0 4px 8px rgba(255, 105, 180, 0.3);
158
+ }
159
+ """
160
+
161
+ # Create the Gradio interface
162
+ with gr.Blocks(theme="soft", css=custom_css) as demo:
163
+ gr.Markdown(f"# {title}")
164
+ gr.Markdown(description)
165
+
166
+ with gr.Row():
167
+ with gr.Column():
168
+ vibe_dropdown = gr.Dropdown(
169
+ choices=[
170
+ "romantic",
171
+ "cheesy",
172
+ "nerdy",
173
+ "cringe",
174
+ "flirty"
175
+ ],
176
+ label="Pick a vibe",
177
+ value="romantic"
178
+ )
179
+ generate_btn = gr.Button("Generate Line", elem_classes="button")
180
+
181
+ with gr.Column():
182
+ output = gr.Textbox(
183
+ label="Your pickup line",
184
+ lines=3,
185
+ interactive=False
186
+ )
187
+ copy_btn = gr.Button("πŸ“‹ Copy to Clipboard", elem_classes="button")
188
+
189
+ # Example inputs
190
+ gr.Examples(
191
+ examples=[
192
+ ["romantic"],
193
+ ["cheesy"],
194
+ ["nerdy"],
195
+ ["cringe"],
196
+ ["flirty"]
197
+ ],
198
+ inputs=[vibe_dropdown]
199
+ )
200
+
201
+ generate_btn.click(
202
+ fn=generate_pickup_line,
203
+ inputs=[vibe_dropdown],
204
+ outputs=output
205
+ )
206
+
207
+ # Footer
208
+ gr.Markdown("""
209
+ <div style="text-align: center; margin-top: 20px; color: #666;">
210
+ Built by Nath with SmolLM πŸ”₯
211
+ </div>
212
+ """)
213
+
214
+ # Launch the app
215
+ if __name__ == "__main__":
216
+ demo.launch(share=True) # Set share=False if you don't want to create a public link