Being able to develop go in an interpreter feels magical. I feel like I can fly through errors or web design iterations. The particular feature I was working on today was something I have been wanting to do for a while, and kind of did with protobufs, but it didn't feel as good as this version.
Going from a go struct -> json schema -> chatgpt prompt -> go struct instance is pretty sick. On top of this, I have the struct -> html form builder which makes this whole thing feel super neat.
Outside of some missing functions BuildForm2
this is pretty much all the code that was needed to pull this off.
r.HandleFunc("/new/ai", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
var recipe Recipe
schema, err := jsonschema.GenerateSchemaForType(recipe)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
req := openai.ChatCompletionRequest{
Model: openai.GPT4oMini,
Messages: []openai.ChatCompletionMessage{
{Role: "system", Content: "You are a professional chef. You provide great recipes."},
{Role: "user", Content: "Create a new recipe for " + r.FormValue("description")},
},
ResponseFormat: &openai.ChatCompletionResponseFormat{
Type: openai.ChatCompletionResponseFormatTypeJSONSchema,
JSONSchema: &openai.ChatCompletionResponseFormatJSONSchema{
Name: "create_recipe",
Schema: schema,
Strict: true,
},
},
}
res, err := d.AI.Client.CreateChatCompletion(context.Background(), req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for _, choice := range res.Choices {
if choice.Message.Role == "assistant" {
err := json.Unmarshal([]byte(choice.Message.Content), &recipe)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
BuildForm2("", recipe, "").RenderPage(w, r)
return
}
DefaultLayout(
Div(
ReloadNode("vote.go"),
Class("container mx-auto mt-10 p-5"),
Form(
HxPost("/vote/new/ai"),
HxTarget("#result"),
Input(Type("text"), Name("description"), Class("input"), Placeholder("Description")),
Button(Class("btn btn-neutral"), Type("submit"), T("Generate Recipe")),
),
Div(Id("result")),
),
).RenderPage(w, r)
return
})
Something I have been thinking about too has been what the feeling of this type of development is starting to unlock. I would like to polish the code builder and put that up for people to use.