form-generatro / app.py
GitHub Action
Deploy form-generator from GitHub: eef63a23b3bc1ffad4a0dc85f8592e8481938620
62065d2
Raw
History Blame Contribute Delete
5.11 kB
"""
Fyltr Form Generator Service (LangGraph).
POST /generate-form: full form from description.
POST /refine-form: surgical diff (changes, additions, removals).
"""
import logging
import os
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from dotenv import load_dotenv
from schema import (
GenerateFormRequest,
GenerateFormResponse,
RefineFormRequest,
RefineFormResponse,
RefineDiff,
PlanFormRequest,
PlanFormResponse,
PlanFormQuestion,
PlanFormQuestionOption,
)
from src.form_generator_workflow import workflow_instance, plan_form_request
load_dotenv()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI(title="Fyltr Form Generator Service", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def root():
return {"message": "Fyltr Form Generator Service", "status": "running"}
@app.get("/health")
async def health():
return {"status": "healthy", "service": "form-generator"}
@app.post("/plan-form-request", response_model=PlanFormResponse)
async def plan_form_request_route(request: PlanFormRequest):
"""Lightweight preflight: decide if we need clarifying questions. No balance deduction."""
if not request.description or not request.description.strip():
return PlanFormResponse(
should_ask_questions=False,
questions=[],
reasoning_summary="",
)
if not os.getenv("OPENAI_API_KEY"):
return PlanFormResponse(
should_ask_questions=False,
questions=[],
reasoning_summary="Service not configured.",
)
result = plan_form_request(
description=request.description.strip(),
current_fields=request.current_fields,
current_title=request.current_title or "",
)
if not result.get("success"):
return PlanFormResponse(
should_ask_questions=False,
questions=[],
reasoning_summary=result.get("error") or "Could not analyze request.",
)
questions = []
for q in result.get("questions") or []:
opts = None
if q.get("options"):
opts = [PlanFormQuestionOption(value=o.get("value", ""), label=o.get("label", "")) for o in q["options"] if isinstance(o, dict)]
questions.append(
PlanFormQuestion(
id=q.get("id", "q"),
label=q.get("label", ""),
type=q.get("type", "text"),
options=opts,
required=bool(q.get("required", True)),
)
)
return PlanFormResponse(
should_ask_questions=result.get("should_ask_questions", False),
questions=questions,
reasoning_summary=result.get("reasoning_summary", "") or "Ready.",
)
@app.post("/generate-form", response_model=GenerateFormResponse)
async def generate_form(request: GenerateFormRequest):
if not request.description or not request.description.strip():
raise HTTPException(status_code=400, detail="description is required and must be non-empty")
if not os.getenv("OPENAI_API_KEY"):
raise HTTPException(status_code=500, detail="OPENAI_API_KEY not configured")
result = workflow_instance.generate_form(
request.description.strip(),
conversation_context=request.conversation_context,
user_goals=request.user_goals,
preferred_field_types=request.preferred_field_types,
must_have_logic=request.must_have_logic,
)
if not result.get("success") or result.get("formJSON") is None:
detail = result.get("error") or "Form generation failed"
raise HTTPException(status_code=422, detail=detail)
return GenerateFormResponse(
formJSON=result["formJSON"],
metadata=result.get("metadata") or {},
warnings=result.get("warnings"),
)
@app.post("/refine-form", response_model=RefineFormResponse)
async def refine_form(request: RefineFormRequest):
if not request.user_request or not request.user_request.strip():
raise HTTPException(status_code=400, detail="user_request is required and must be non-empty")
if not os.getenv("OPENAI_API_KEY"):
raise HTTPException(status_code=500, detail="OPENAI_API_KEY not configured")
result = workflow_instance.refine_form(
user_request=request.user_request.strip(),
current_fields=request.current_fields,
current_title=request.current_title or "",
conversation_context=request.conversation_context,
)
if not result.get("success") or result.get("diff") is None:
detail = result.get("error") or "Form refine failed"
raise HTTPException(status_code=422, detail=detail)
diff = result["diff"]
return RefineFormResponse(
diff=RefineDiff(
changes=diff.get("changes", []),
additions=diff.get("additions", []),
removals=diff.get("removals", []),
)
)