generated from westfarn/web_django_template
Initial commit
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SocialAiConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "social_ai"
|
||||
verbose_name = "AI social generator"
|
||||
|
||||
def ready(self):
|
||||
from social_ai import hooks
|
||||
|
||||
hooks.register()
|
||||
@@ -0,0 +1,5 @@
|
||||
from core.registry import register_feature
|
||||
|
||||
|
||||
def register() -> None:
|
||||
register_feature("social_ai")
|
||||
@@ -0,0 +1,63 @@
|
||||
"""Ollama client for drafting social posts."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OllamaError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def generate_social_post(
|
||||
prompt: str,
|
||||
*,
|
||||
platform: str = "",
|
||||
tone: str = "professional, warm, on-brand",
|
||||
) -> str:
|
||||
"""
|
||||
Call the LAN Ollama endpoint (default http://10.0.0.128:11434) to draft copy.
|
||||
|
||||
Uses the standard Ollama /api/generate HTTP API.
|
||||
"""
|
||||
base = (settings.OLLAMA_BASE_URL or "").rstrip("/")
|
||||
if not base:
|
||||
raise OllamaError("OLLAMA_BASE_URL is not configured")
|
||||
|
||||
system = (
|
||||
"You write short social media posts for a local business. "
|
||||
f"Tone: {tone}. "
|
||||
"Return only the post text, no preamble."
|
||||
)
|
||||
if platform:
|
||||
system += f" Optimize for {platform}."
|
||||
|
||||
full_prompt = f"{system}\n\nUser request:\n{prompt}"
|
||||
|
||||
url = f"{base}/api/generate"
|
||||
payload = {
|
||||
"model": settings.OLLAMA_MODEL,
|
||||
"prompt": full_prompt,
|
||||
"stream": False,
|
||||
}
|
||||
try:
|
||||
response = requests.post(
|
||||
url,
|
||||
json=payload,
|
||||
timeout=settings.OLLAMA_TIMEOUT_SECONDS,
|
||||
)
|
||||
response.raise_for_status()
|
||||
except requests.RequestException as exc:
|
||||
logger.exception("Ollama request failed")
|
||||
raise OllamaError(f"Ollama unreachable at {url}: {exc}") from exc
|
||||
|
||||
data = response.json()
|
||||
text = (data.get("response") or "").strip()
|
||||
if not text:
|
||||
raise OllamaError("Ollama returned empty response")
|
||||
return text
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.urls import path
|
||||
|
||||
from social_ai import views
|
||||
|
||||
app_name = "social_ai"
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.api_generate, name="generate"),
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
import json
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from social_ai.ollama import OllamaError, generate_social_post
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def api_generate(request):
|
||||
"""JSON endpoint to draft posts via Ollama. POST JSON: prompt, platform."""
|
||||
try:
|
||||
payload = json.loads(request.body.decode() or "{}")
|
||||
except json.JSONDecodeError:
|
||||
payload = request.POST.dict()
|
||||
prompt = (payload.get("prompt") or "").strip()
|
||||
if not prompt:
|
||||
return JsonResponse({"error": "prompt required"}, status=400)
|
||||
try:
|
||||
text = generate_social_post(
|
||||
prompt, platform=(payload.get("platform") or "").strip()
|
||||
)
|
||||
except OllamaError as exc:
|
||||
return JsonResponse({"error": str(exc)}, status=502)
|
||||
return JsonResponse({"text": text})
|
||||
Reference in New Issue
Block a user