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
	})

Screenshot 2024-10-15 at 10.36.57 PM.png

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.