Files
bot/ai_generator.py
2026-05-18 14:15:59 +07:00

243 lines
9.3 KiB
Python

import os
import json
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
# Setup OpenRouter Client
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY"),
)
# Load data pool
with open('bot_data_pool.json', 'r') as f:
data_pool = json.load(f)
DATA_SOURCE = os.getenv("DATA_SOURCE", "AI").upper()
USED_DATA_FILE = "used_data.txt"
def load_used_data():
"""Loads all used names, services, and jobs into a dictionary of sets to prevent duplicates"""
used = {"names": set(), "services": set(), "jobs": set()}
if os.path.exists(USED_DATA_FILE):
with open(USED_DATA_FILE, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if ":" in line:
parts = line.split(":", 1)
key = parts[0].strip().lower()
val = parts[1].strip().lower()
if key in used:
used[key].add(val)
return used
def save_used_item(item_type, val):
"""Saves a single used item to our persistent text tracking file"""
val_clean = val.strip()
if not val_clean:
return
with open(USED_DATA_FILE, "a", encoding="utf-8") as f:
f.write(f"{item_type}:{val_clean}\n")
def generate_from_pool():
"""Mengambil data secara acak langsung dari data pool dengan memfilter data yang sudah dipakai"""
import random
used = load_used_data()
# Filter available unique names
available_names = [n for n in data_pool['names'] if n.strip().lower() not in used['names']]
if not available_names:
available_names = data_pool['names'] # Fallback if pool is depleted
name1 = random.choice(available_names)
# Select unique name2
available_names_for_2 = [n for n in available_names if n != name1]
if not available_names_for_2:
available_names_for_2 = [n for n in data_pool['names'] if n != name1]
name2 = random.choice(available_names_for_2)
# Filter unique service titles
available_services = [
s for s in data_pool['service_titles']
if s.strip().lower() not in used['services'] and s.strip().lower() not in used['jobs']
]
if not available_services:
available_services = data_pool['service_titles']
title = random.choice(available_services)
# Select random addresses
addr1 = random.choice(data_pool['addresses'])
addr2 = random.choice(data_pool['addresses'])
return {
"akun1": {
"nama_lengkap": name1,
"email": f"{name1.lower().replace(' ', '.')}@gmail.com",
"nama_bisnis": name1,
"deskripsi_bisnis": f"Penyedia jasa {title} profesional dan terpercaya.",
"lokasi": {
"lat": str(-6.2088 + (random.random() * 0.1)),
"lng": str(106.8456 + (random.random() * 0.1)),
"alamat": addr1,
"radius": "50"
},
"identitas": {
"tipe": "KTP",
"nomor": str(random.randint(1000000000000000, 9999999999999999))
}
},
"akun2": {
"nama_lengkap": name2,
"email": f"{name2.lower().replace(' ', '.')}@gmail.com"
},
"layanan": {
"judul": title,
"deskripsi": f"Saya menawarkan layanan {title} dengan hasil kualitas terbaik. Pengalaman sudah lebih dari 3 tahun di bidang ini.",
"harga": random.choice([50000, 75000, 100000, 150000, 200000, 500000])
},
"review": {
"rating": "5",
"komentar": random.choice([
"Sangat puas dengan hasilnya!",
"Kerja cepat dan rapi, mantap.",
"Sangat direkomendasikan untuk jasa ini.",
"Komunikasi baik dan hasil sesuai ekspektasi.",
"Terima kasih banyak, sangat membantu."
])
}
}
def generate_bot_data():
"""Menghasilkan data bot berdasarkan DATA_SOURCE (AI atau POOL) dengan jaminan tanpa duplikat"""
if DATA_SOURCE == "POOL":
data = generate_from_pool()
# Save pool data to tracking log
save_used_item("names", data["akun1"]["nama_lengkap"])
save_used_item("names", data["akun2"]["nama_lengkap"])
if "layanan" in data and "judul" in data["layanan"]:
save_used_item("services", data["layanan"]["judul"])
save_used_item("jobs", data["layanan"]["judul"])
return data
import random
used = load_used_data()
# Filter only active/fresh items to send in prompt context
used_names_str = ", ".join(list(used['names'])[:100]) # Last 100 names to keep prompt lightweight
used_services_str = ", ".join(list(used['services'])[:100])
names_sample = str(random.sample(data_pool['names'], min(15, len(data_pool['names']))))
service_titles_sample = str(random.sample(data_pool['service_titles'], min(10, len(data_pool['service_titles']))))
job_titles_sample = str(random.sample(data_pool['job_titles'], min(10, len(data_pool['job_titles']))))
addresses_sample = str(random.sample(data_pool['addresses'], min(10, len(data_pool['addresses']))))
# Jika mode AI
prompt = f"""
Anda adalah asisten AI yang bertugas men-generate data JSON untuk simulasi marketplace jasa (Microjob).
GUIDELINE PENAMAAN (Wajib Diikuti):
- Nama Orang: Gunakan referensi seperti {names_sample}... (Hanya nama asli orang Indonesia).
- Nama Bisnis: HARUS sama dengan Nama Lengkap orang tersebut (Jangan gunakan tambahan 'Design', 'Solusi', dll).
- Judul Layanan: Gunakan pola seperti {service_titles_sample}...
- Judul Job: Gunakan pola seperti {job_titles_sample}...
- Alamat: Gunakan referensi pola seperti {addresses_sample}...
ATURAN ANTI-DUPLIKASI (PENTING!):
- JANGAN GUNAKAN NAMA BERIKUT KARENA SUDAH PERNAH DIGUNAKAN (DUPLIKAT):
{used_names_str if used_names_str else 'Belum ada'}
- JANGAN GUNAKAN JUDUL LAYANAN ATAU JUDUL JOB BERIKUT KARENA SUDAH PERNAH DIGUNAKAN (DUPLIKAT):
{used_services_str if used_services_str else 'Belum ada'}
Aturan Tambahan:
1. JANGAN gunakan nama artis, tokoh publik, atau selebriti.
2. JANGAN ada kata 'bot' di data manapun.
3. Output harus valid JSON.
Struktur JSON:
{{
"akun1": {{
"nama_lengkap": "Nama asli orang Indonesia yang realistis (Hanya nama orang biasa, misal: Budi Santoso, Siti Aminah)",
"email": "Email pribadi realistis berdasarkan nama",
"nama_bisnis": "Gunakan nama orang saja (Hanya nama, jangan gunakan tambahan 'Solusi Digital', 'Design', 'Jasa', dll)",
"deskripsi_bisnis": "Deskripsi singkat tentang keahlian atau layanan yang ditawarkan",
"lokasi": {{
"lat": "Latitude acak di area perkotaan Indonesia (misal: Jakarta, Bandung, atau Surabaya)",
"lng": "Longitude acak di area perkotaan Indonesia",
"alamat": "Alamat lengkap realistis di Indonesia",
"radius": "Angka radius layanan dalam KM (antara 10-100)"
}},
"identitas": {{
"tipe": "KTP",
"nomor": "16 digit angka KTP acak yang valid secara format"
}}
}},
"akun2": {{
"nama_lengkap": "Nama asli pembeli Indonesia yang realistis (Hanya nama orang biasa)",
"email": "Email pribadi realistis berdasarkan nama"
}},
"layanan": {{
"judul": "Judul jasa yang ditawarkan (HARUS Unik dan Kreatif)",
"deskripsi": "Deskripsi lengkap layanan tersebut",
"harga": 50000
}},
"review": {{
"rating": 5,
"komentar": "Komentar positif dari pembeli"
}}
}}
Berikan HANYA JSON output tanpa teks lain.
"""
max_retries = 5
attempt = 0
while attempt < max_retries:
try:
response = client.chat.completions.create(
model="google/gemini-3-flash-preview",
messages=[
{"role": "system", "content": "You output only valid JSON."},
{"role": "user", "content": prompt}
]
)
content = response.choices[0].message.content.strip()
# Strip markdown backticks if present
if content.startswith("```"):
content = content.split("```")[1]
if content.startswith("json"):
content = content[4:]
content = content.split("```")[0].strip()
data = json.loads(content)
# Commit successfully generated items to our local used data file
save_used_item("names", data["akun1"]["nama_lengkap"])
save_used_item("names", data["akun2"]["nama_lengkap"])
if "layanan" in data and "judul" in data["layanan"]:
save_used_item("services", data["layanan"]["judul"])
save_used_item("jobs", data["layanan"]["judul"])
return data
except Exception as e:
attempt += 1
print(f"Error generating AI data (Attempt {attempt}/{max_retries}): {e}")
if attempt < max_retries:
import time
time.sleep(3)
else:
print("Max retries reached. AI generation failed.")
raise e
if __name__ == "__main__":
print(generate_bot_data())