rag_template / scripts /setup_neon.py
Guilherme Favaron
Sync: Complete project update (Phase 6) - API, Metadata, Eval, Docs
a686b1b
"""
Script interativo para configurar Neon para RAG Template.
Facilita a configuracao do DATABASE_URL e testa a conexao.
"""
import os
import sys
from urllib.parse import quote_plus
def print_header():
"""Imprime o cabecalho do script."""
print("=" * 60)
print(" Setup Neon para RAG Template")
print("=" * 60)
print()
def get_connection_string():
"""Solicita a connection string do Neon."""
print("1. Obter Connection String")
print(" - Acesse seu projeto no Neon")
print(" - Va para Connection Details")
print(" - Copie a Connection String completa")
print(" - Formato: postgresql://user:pass@ep-xxx.neon.tech/neondb?sslmode=require")
print()
print(" DICA: Voce pode colar a string completa aqui")
print()
conn_string = input("Connection String: ").strip()
return conn_string
def validate_connection_string(conn_string: str) -> bool:
"""Valida se a connection string tem formato correto."""
if not conn_string.startswith("postgresql://"):
return False
if "neon.tech" not in conn_string:
return False
return True
def ensure_ssl_mode(conn_string: str) -> str:
"""Garante que sslmode=require esta presente."""
if "sslmode=require" not in conn_string:
separator = "?" if "?" not in conn_string else "&"
conn_string += f"{separator}sslmode=require"
print(" [INFO] Adicionado sslmode=require a URL")
return conn_string
def save_to_env(database_url: str) -> bool:
"""Salva DATABASE_URL no arquivo .env."""
print("\n2. Salvar no .env")
# Verificar se .env ja existe
env_path = ".env"
if os.path.exists(env_path):
print(f" Arquivo .env encontrado")
overwrite = input(" Sobrescrever DATABASE_URL existente? (s/n): ").strip().lower()
if overwrite != 's':
print(" Pulando salvamento no .env")
return False
# Ler conteudo existente
existing_content = ""
if os.path.exists(env_path):
with open(env_path, 'r') as f:
lines = f.readlines()
# Remover linha DATABASE_URL existente
existing_content = "".join(
line for line in lines if not line.startswith("DATABASE_URL=")
)
# Adicionar nova DATABASE_URL
with open(env_path, 'w') as f:
f.write(existing_content)
if existing_content and not existing_content.endswith('\n'):
f.write('\n')
f.write(f"DATABASE_URL={database_url}\n")
print(f" DATABASE_URL salvo em {env_path}")
return True
def test_connection(database_url: str) -> bool:
"""Testa a conexao com o banco."""
print("\n3. Testar Conexao")
test = input(" Testar conexao agora? (s/n): ").strip().lower()
if test != 's':
print(" Pulando teste de conexao")
return False
try:
# Importar aqui para nao quebrar se dependencias nao instaladas
import psycopg
from psycopg import sql
print(" Conectando ao Neon...")
with psycopg.connect(database_url) as conn:
with conn.cursor() as cur:
# Testar conexao
cur.execute("SELECT version();")
version = cur.fetchone()[0]
print(f" Conexao bem-sucedida!")
print(f" PostgreSQL version: {version[:50]}...")
# Verificar extensao pgvector
cur.execute(
"SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'vector');"
)
has_vector = cur.fetchone()[0]
if has_vector:
print(" Extensao pgvector: INSTALADA")
else:
print(" Extensao pgvector: NAO ENCONTRADA")
print("\n Para instalar, execute no SQL Editor do Neon:")
print(" CREATE EXTENSION vector;")
# Verificar storage usado
cur.execute(
"SELECT pg_size_pretty(pg_database_size(current_database()));"
)
db_size = cur.fetchone()[0]
print(f" Database size: {db_size}")
return True
except ImportError:
print(" ERRO: psycopg nao instalado")
print(" Execute: pip install psycopg[binary]")
return False
except Exception as e:
print(f" ERRO ao conectar: {e}")
print("\n Verifique:")
print(" - Connection string correta")
print(" - Projeto Neon ativo")
print(" - Firewall nao bloqueando conexao")
return False
def print_tips():
"""Imprime dicas sobre o Neon."""
print("\n" + "=" * 60)
print(" Dicas Neon")
print("=" * 60)
print("\n Free Tier:")
print(" - 10GB storage")
print(" - 100 compute hours/mes")
print(" - 10 projetos")
print(" - 10 branches por projeto")
print("\n Branching:")
print(" - Crie branches para testes sem afetar producao")
print(" - Cada branch tem sua propria connection string")
print("\n Performance:")
print(" - Use connection pooling (?pooler=true na URL)")
print(" - Neon pausa automaticamente apos 5min inatividade")
print(" - Cold start geralmente <2s")
def print_next_steps(success: bool):
"""Imprime proximos passos."""
print("\n" + "=" * 60)
print(" Proximos Passos")
print("=" * 60)
if success:
print("\n Conexao configurada com sucesso!")
print("\n 1. Habilite pgvector (se nao habilitado):")
print(" - Va ao SQL Editor no Neon")
print(" - Execute: CREATE EXTENSION vector;")
print("\n 2. Configure HF_TOKEN no .env:")
print(" HF_TOKEN=seu_token_huggingface")
print("\n 3. Execute o app:")
print(" python app.py")
print("\n 4. Acesse: http://localhost:7860")
else:
print("\n Configure DATABASE_URL manualmente no .env:")
print(" DATABASE_URL=postgresql://user:pass@ep-xxx.neon.tech/neondb?sslmode=require")
print("\n Ou execute este script novamente")
print("\n Documentacao completa: docs/NEON_SETUP.md")
print("=" * 60)
def main():
"""Funcao principal."""
print_header()
# Coletar connection string
conn_string = get_connection_string()
if not conn_string:
print("ERRO: Connection string vazia")
sys.exit(1)
# Validar formato
if not validate_connection_string(conn_string):
print("ERRO: Connection string invalida")
print("Formato esperado: postgresql://user:pass@ep-xxx.neon.tech/neondb")
sys.exit(1)
# Garantir SSL mode
database_url = ensure_ssl_mode(conn_string)
print("\n" + "=" * 60)
print(" DATABASE_URL Configurado")
print("=" * 60)
print(f"\n{database_url}\n")
# Salvar no .env
saved = save_to_env(database_url)
# Testar conexao
success = test_connection(database_url)
# Dicas
if success:
print_tips()
# Proximos passos
print_next_steps(success and saved)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\nSetup cancelado pelo usuario")
sys.exit(0)