UNPKG

ai-native-form

Version:

AI-powered React form assistant with GPT-4, speech input, and schema auto-generation.

84 lines (83 loc) 3.32 kB
import { useFormContext, } from "react-hook-form"; import { useRef } from "react"; export function useAIForm(form, apiKey) { const context = useFormContext(); const resolvedForm = form ?? context; if (!resolvedForm) { throw new Error("❌ useAIForm: No form context or object provided."); } const { setValue, register: baseRegister } = resolvedForm; const schemaRef = useRef({ type: "object", properties: {}, required: new Set(), transformers: {}, }); const register = (name, options) => { const fieldType = options?.type || "string"; schemaRef.current.properties[name] = { type: fieldType }; if (options?.required) schemaRef.current.required.add(name); return baseRegister(name, options); }; const registerController = (name, meta) => { schemaRef.current.properties[name] = { type: meta.type || "string", }; if (meta.enum) { schemaRef.current.properties[name].enum = meta.enum; } if (meta.required) { schemaRef.current.required.add(name); } if (meta.transform) { schemaRef.current.transformers[name] = meta.transform; } }; const getSchema = () => ({ type: "object", properties: schemaRef.current.properties, required: Array.from(schemaRef.current.required), }); const fillFromPrompt = async (prompt) => { if (!apiKey) throw new Error("❌ No OpenAI API key provided"); const schema = getSchema(); const res = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ model: "gpt-4-1106-preview", messages: [ { role: "system", content: "You are a helpful assistant that fills out form fields from user prompts.", }, { role: "user", content: prompt }, ], tools: [ { type: "function", function: { name: "fillForm", description: "Fills out a form based on the user's natural language prompt. Use strictly the information provided by the user; if a field's information is not within the user's prompt, do not fill it. ", parameters: schema, }, }, ], tool_choice: { type: "function", function: { name: "fillForm" } }, }), }); const result = await res.json(); const args = JSON.parse(result.choices[0].message.tool_calls[0].function.arguments); Object.entries(args).forEach(([key, value]) => { const transformer = schemaRef.current.transformers[key]; const finalValue = transformer ? transformer(value) : value; setValue(key, finalValue); }); }; return { register, registerController, fillFromPrompt, getSchema }; }