Author: Richard Seroter

  • Daily Reading List – January 16, 2024 (#240)

    I had a quiet day in London, meeting with friends and getting work done. The event I’m here for starts tomorrow morning. In the meantime, i got to build some things today, and read a fair bit. Check out the list below.

    [article] How Apple built iCloud to store billions of databases. This offers a detailed look at what Apple’s said publicly about their architecture and how it works.

    [article] From Potential to Profit with GenAI. Lots of interesting data here. The investment in generative AI is big, but so are expectations. Many are looking for cost savings in 2024, which may be unrealistic.

    [article] HOWTO: Change your behavior. Are there things you’d like to start doing or stop doing? Probably, if you’re a human being. Read this for some perspective on what it takes to change.

    [blog] Sign in with Google in Go. If you built an app that lets users sign in with existing identities, your users probably thank you. This post shows two options for incorporating Google identities.

    [article] 11 reasons the new Java is not like the old Java. Too many folks are building with old versions of Java, but maybe all these recent additions to the language will encourage folks to upgrade.

    [blog] Deploy, Don’t Delay: Streamlining model deployment with Vertex AI Deployer. This is a very good walkthrough of how to deploy trained ML models to Vertex using our continuous delivery service.

    [article] The Best Leaders Can’t Be Replaced by AI. Right now, you’re not going to AI for what makes a good leader: compassion, awareness, or wisdom.

    [blog] Test-Driven Development (TDD), Building ‘Hello World’ in Go. I can’t say I’ve seen much (any?) writeups about testing Go apps. This one jumped out at me, and was solid.

    [blog] Coming Soon: Golang 1.22. It feels to me that language changes are coming faster (it’s probably just in my head), so I like these types of posts that bubble up the changes that matter most.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 15, 2024 (#239)

    Greetings from London! I arrived yesterday and spent today at our office working with our local sales engineering team. Great bunch of proper experts.

    [article] Many software developers don’t trust AI – report. That’s the headline, but inside, you also see that 70% of devs think AI will help, and 60% want to use AI. But, there’s work to do for us all to trust it more.

    [article] Wells Fargo’s assistant, powered by Google’s AI, poised to hit 100 million interactions annually. Good recipe: orient towards legit use cases, deeply train your staff, pick partners that help you get to production quickly.

    [blog] Databases upgrade made easy with in-place major version upgrades on Cloud SQL. For support reasons alone, it’s important to keep up with database engine versions. It’s hard though. I like when solutions like this exist, especially when you can keep the name/IP the same.

    [article] Applying the SPACE Framework. It’s less prescriptive that DORA, but the SPACE framework offers a more rich view of the “developer productivity” lens for tech teams. I suspect that many folks will use both to uplevel their teams.

    [blog] Can large language models identify and correct their mistakes? Some cool research here, and the idea seems reasonable.

    [blog] 5 Steps to Debug Development and Operations Teams. If you inherit a struggle team, or wake and realize your own team is struggling, this article offers helpful guidance for figuring out where the issue is.

    [blog] Troubleshooting distributed applications: Using traces and logs together for root-cause analysis. I’d bet that most all of you have mature logging and monitoring processes. But how many of you heavily use distributed tracing to find latency issues? Here’s a good post about how it works.

    [article] How to Lead Across a Siloed Organization. It’s probably rare nowadays for someone to NOT work with a lot of people across different functions or organizations. If that’s hard for you—as it is for most of us—this guidance should help.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 12, 2024 (#238)

    Did you have an interesting week? I hope you learned a few things and met someone new. I’m off to London tomorrow for a week of work stuff, but will continue publishing this reading list while I’m there. It’s just possible I mix in some “bloody hell” mentions while complaining about lorries and loos.

    [article] Celebrating 20+ Years of Domain Driven Design (DDD) and EIP. These are classic books that still apply today. Here’s a look at their impact, with input from the authors.

    [blog] Cloud Deploy gains support for custom target types. I really like the ability to use a single continuous deployment engine to along with a variety of “targets” like an MLOps platform or GitOps-style rollout.

    [article] A Simple Hack to Help You Communicate More Effectively. Are you a good communicator when put on the spot? This article has a good framework to use for spontaneous or planned communication.

    [blog] Deploying Go API on GKE | Google Cloud. I like this end to end walkthrough that covers account setup, Kubernetes cluster setup, and database configuration.

    [article] You probably have too many SaaS apps. Seems accurate. There are lots of specialized products which are great, but there must be room to consolidate to fewer, good-enough products.

    [blog] Announcing Humboldt, the first cable route between South America and Asia-Pacific. Satellites are awesome, but much of the internet traffic goes under the sea.

    [article] Snyk’s AI Code Security Report Reveals Software Developers’ False Sense of Security. Even though the AI-generated code may (or may not) be high quality, it doesn’t mean you skip important steps around code scanning!

    [blog] Rebuilding Netflix Video Processing Pipeline with Microservices. Here’s a deep dive into Netflix’s work to take a mature product and rebuild it as microservices.

    [blog] How Deutsche Bank achieved high availability and scalability with Spanner. Powerful cloud-native databases are just for funky Vally startups, right? Nah. All sorts of companies benefit from low-maintenance, elastic database engines.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 11, 2024 (#237)

    Another day of drowning in meetings, but at least I’m drowning gracefully. I enjoyed the handful of pieces I got a chance to read, and bet you’ll like one or two of them too.

    [blog] Analyzing Go Binary Sizes. It’s easy to ignore the ever-growing size of our compiled components, but you’re doing yourself a favor by understanding why a binary is bloated, and how to shrink it.

    [article] 9 extraordinary documents every developer should read. It’s good to stop and reflect on what came before us. Here are some classic papers that are useful to review.

    [article] How Golang Manages Its Security Supply Chain. I genuinely hope the things the Go team does become standard with the other major languages. It’d go a long way to improving the security posture of countless systems.

    [blog] Laying the foundation for a career in platform engineering. We see lots of companies embrace the concept of platform engineering, but what does it take to build a career as a platform engineer? I like this post and what it covers.

    [article] Reliable Architectures Through Observability. Observability is such an over-used term now, but I trust the folks at Honeycomb to clearly describe it. Good read here.

    [blog] Cloud switching just got easier: Removing data transfer fees when moving off Google Cloud. I don’t want you to go, but if you do, it shouldn’t be unnecessarily costly. I like that we did this.

    [blog] Evolution of Developer Productivity at Square – Part One. Good story about improving continuous integration experiences for developers as part of an effort to invest in developer productivity.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 10, 2024 (#236)

    This is supposed to be a “light meeting” week at work. In unrelated news, I had twelve meetings today. Fortunately, there wasn’t a dud in a bunch and I could still make time to read some interesting items today.

    [article] When Your Boss Gives You a Totally Unrealistic Goal. Hey, I did this to my team yesterday! But on purpose. Outlandish goals force unconstrained thinking. We do the best we can, and no one (on my team) will get dinged because we didn’t reach it. Aim high.

    [article] What Temperature Means in Natural Language Processing and AI. Have you noticed this property in LLM APIs or UIs? This article explains what temperature is about.

    [docs] Perform automatic side-by-side evaluation. Wow, evaluate the performance of two LLMs, side by side to see which gives better responses? This is now part of Vertex AI.

    [blog] Introducing the Dataflow ML Starter project: A practical template to develop and deploy Dataflow ML jobs. While I don’t use “starter projects” as my actual baseline, I do often use these sorts of things as a way to learn, and then copy aspects I want to reuse.

    [article] The return of the majestic monolith. Long post, but good points about doing what’s right for your use case, not just what’s trendy.

    [blog] 2024 Predictions from the Condensing the Cloud Team. The Battery Ventures team has a pulse on what the market is buying, so I’ll listen to predictions from these VCs. Many of these feel spot on.

    [blog] Getting started with AI notebooks and Jupyterhub on GKE. Is your team doing more with Jupyter notebooks? If so, you likely have some platform for folks to interact with them. Here’s a way to run such an experience on Kubernetes.

    [blog] 10 microservices design patterns for better architecture. The Capital One team has another good post that looks at some common design patterns for those doing microservices.

    [blog] Gemini, the stylist… Would you trust an LLM to offer to hairstyle suggestions? Um, maybe? Abi built a fun app that used Gemini and Imagen2 to create suggestions that she accepted.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 9, 2024 (#235)

    I cover a fair amount of “developer productivity” and “developer happiness” content in this reading list. Admittedly, I’m drawn to it. It’s not about pampered developers who do what they want and everyone caters to them. Rather, it’s about unleashing a valuable asset and holding them accountable for excellence by giving them what they need to succeed.

    [article] What Is Active Listening? Being a good listener is a choice. One that takes a lot of effort, but has a material impact on those around you. I liked this article about active listening.

    [blog] Software Quality. In measuring developer productivity, how does Google look at “quality” metrics? This post explores a new paper from us that digs into four dimensions of quality.

    [blog] Step by step guide to deploying spring boot application on Google Cloud Run. Good little demo. I like that it starts at the very beginning of the process and doesn’t assume much.

    [article] 2023: The Year Open Source Security Supply Chain Grew Up. From the surveys and data I’ve seen, we have a long way to go before we’re all good at securing our software supply chains. But there’s progress, and the tech itself is getting better.

    [article] Code with Duet AI Live! Join Google experts for a weekly live coding and Q&A event series. We have a lot to learn about how generative AI tooling helps devs. If you want to watch a couple of pros figure it out live, you’ll like this weekly live coding series that starts on January 17th.

    [article] Unleash Your Coding Superpowers: The Epic Tale of Customising My Cloud Development Environment with a Side of Java (Coffee, That Is!). Cloud dev environments are getting more popular, and I like when folks show how to customize them to their specific needs.

    [article] 10 ways to destroy developer happiness. Don’t do these things to developers. Or frankly, most anyone in technology roles.

    [blog] TDD: For Those Who Don’t Know How to Design Software. That’s a pretty frisky blog title. Well done. JB shares an interesting take on the usefulness of test driven development.

    [blog] 3 predictions for AI in healthcare in 2024. I’ve gotten fairly cynical on vendor-driven predictions (even from my own employer), but these are pretty reasonable ones.

    [article] It’s time to fix flaky tests in software development. Tests that sometimes work, and sometimes don’t, even when the code doesn’t change. Not fun. Trisha says you can’t ignore these flaky tests, and need to focus on resolving them.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 8, 2024 (#234)

    Happy Monday! This looks like it’ll be my first 5-day workweek in a while. You too? I cleared out some of my reading queue today, and saw lots of great material. Jump in.

    [blog] Product Managing to Prevent Burnout. To me, a great product manager is one who protects their team. They keep engineers focused on priorities and out of useless meetings, and encourages sustainable pace. This article does a great job explaining this.

    [article] A Guide for Getting Stakeholder Buy-In for Your Agenda. Most of us eventually learn that a great idea won’t matter if you can’t get people to buy into it. This article has a good framework to think through if you want to advance our ideas within your company.

    [article] How the GenAI Revolution Reminds Us of 1990s Computing. Is there nothing new under the sun? Janakiram see parallels between the current generative AI era and the 1990s computing era.

    [blog] Our move to generated SDKs. GitHub is moving towards software-generated SDKs with the goal of more structured and regularly-updated bits. .NET and Go are the first two languages supported.

    [blog] Google Cloud Vertex AI and dotnet : HCIH App. Speaking of .NET, this post shows how an ASP.NET website can call generative AI services and get hosted in Cloud Run.

    [blog] Advice on using LLMs wisely. My former colleague is a great follow on LinkedIn and has shared some smart perspectives on generative AI over the past few months.

    [blog] Free technical writing courses. Are you an engineer who wants to be a better technical writer? These upcoming courses from Google are free to take.

    [blog] Go 1.22: Interactive release notes. Not only do you learn about new features in this post, but you can try them inline without leaving the page. Very cool.

    [blog] 22 reasons to ditch Azure DevOps and switch to GitHub as soon as possible. I’ve been unclear on whether these would stay separate products or what, but Dennis encourages people to go to the more complete GitHub experience.

    [blog] Engineering Transformations – Adopting Automated Testing As A Practice. Generative AI can help you slap more tests into your codebase, but that doesn’t magically give you a good testing culture. This post looks at why automated tests matter, failure modes, and strategies for success.

    [blog] Event Streaming: Tips for Event-Driven Apps. The engineering team at Capital One explains what event streaming is all about and how you can do it too.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 5, 2024 (#233)

    If you’re still on holiday break, drink in your remaining hours. For those of us who returned to work this week, how was it? I’m glad to be back, and am excited about the year ahead.

    [article] The Hard Questions to Ask When Planning Your Strategy. This article says that strategy can be defined as answering “where are we now”, “where do we want to go”, and “what is a credible path to get there.” But many aren’t honest with themselves about the first question.

    [article] WebAssembly in 2024: Components Are and Are Not the Big Story. Is this the year that Wasm breaks through? Is the tech almost ready, and are the use cases compelling enough? This post looks at a major piece that’s near completion. And here are predictions for 2024.

    [blog] Simplify speech analytics with BigQuery, powered by Vertex AI. I like the idea of transcribing speech files and being able to mix that with other structured data. Now in preview.

    [blog] How to Choose Developer Events. Which events should you sponsor this year? Relatedly, I wonder how many of you are choosing which events to attend as well.

    [blog] Angular Developer Survey 2023. User surveys are a powerful way to get ideas and feedback about your product. The Angular team uses these to help prioritize their roadmap.

    [blog] Bazel 7 Release. Each language/framework has their own build system(s), but there’s something powerful about having a single build engine regardless of language, OS, or platform. This latest LTS release of Bazel offers some terrific updates.

    [blog] Management. Have you hugged your manager today? I mean, don’t get fired for being creepy, but have you stopped to appreciate the role and their efforts? This post looks at the noble profession and hard work it takes to be good at it.

    [blog] What We Got Right, What We Got Wrong. An honest retrospective is a powerful thing. Rob looks at the early days of the Go language.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Daily Reading List – January 4, 2024 (#232)

    I had a good day getting some items completed, while also learning and writing a bit. Many of the pieces below are useful for those thinking through 2024 strategies.

    [article] Observability in 2024: More OpenTelemetry, Less Confusion. “Observability” is a noisy space, and every monitoring vendor now calls themselves an observability vendor. But that doesn’t mean that there’s not a lot of important work in this area.

    [article] Employees turn to generative AI for research, data analysis as 2024 kicks off. Breaking news! People are using generative AI at work. That’s not surprisingly anymore; but the depth of usage soon will be.

    [blog] Choosing between Cloud Run and GKE. Here’s a short post for those deciding between the two primary container-based runtimes in Google Cloud. For me, if you have a lot of code/components and want the Kubernetes API, choose GKE Autopilot. If you have glue apps or standalone apps, pick Cloud Run.

    [article] Legacy Seam. This post from Martin Fowler looks at finding seams in your legacy code base and changing behavior without editing source code.

    [blog] Coding at Google. Eric was at Microsoft, then Google, now back at Microsoft, but he offers up a terrific look at the platforms and processes we give to our devs so they can do their best work.

    [article] Software supply chain security remains a challenge for most enterprises. Are you part of the 12% who are successful at remediating vulnerabilities in your company? Or are you struggling like most everyone else?

    [blog] Providing Backup and Disaster Recovery as a Service. Good details from the engineering team at Flipkart.

    [blog] Building Pinterest’s new wide column database using RocksDB. You shouldn’t go around building databases very often, but it makes sense for certain folks. Here’s what Pinterest did.

    ##

    Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:

  • Make Any Catalog-Driven App More Personalized to Your Users: How I used Generative AI Coding Tools to Improve a Go App With Gemini.

    Make Any Catalog-Driven App More Personalized to Your Users: How I used Generative AI Coding Tools to Improve a Go App With Gemini.

    How many chatbots do we really need? While chatbots are a terrific example app for generative AI use cases, I’ve been thinking about how developers may roll generative AI into existing “boring” apps and make them better.

    As I finished all my Christmas shopping—much of it online—I thought about all the digital storefronts and how they provide recommended items based on my buying patterns, but serve up the same static item descriptions, regardless of who I am. We see the same situation with real estate listings, online restaurant menus, travel packages, or most any catalog of items! What if generative AI could create a personalized story for each item instead? Wouldn’t that create such a different shopping experience?

    Maybe this is actually a terrible idea, but during the Christmas break, I wanted to code an app from scratch using nothing but Google Cloud’s Duet AI while trying out our terrific Gemini LLM, and this seemed like a fun use case.

    The final app (and codebase)

    The app shows three types of catalogs and offers two different personas with different interests. Everything here is written in Go and uses local files for “databases” so that it’s completely self-contained. And all the images are AI-generated from Google’s Imagen2 model.

    When the user clicks on a particular catalog entry, the go to a “details” page where the generic product summary from the overview page is sent along with a description of the user’s preferences to the Google Gemini model to get a personalized, AI-powered product summary.

    That’s all there is to it, but I think it demonstrates the idea.

    How it works

    Let’s look at what we’ve got here. Here’s the basic flow of the AI-augmented catalog request.

    How did I build the app itself (GitHub repo here)? My goal was to only use LLM-based guidance either within the IDE using Duet AI in Google Cloud, or burst out to Bard where needed. No internet searches, no docs allowed.

    I started at the very beginning with a basic prompt.

    What are the CLI commands to create a new Go project locally?

    The answer offered the correct steps for getting the project rolling.

    The next commands are where AI assistance made a huge difference for me. With this series of natural language prompts in the Duet AI chat within VS Code, I got the foundation of this app set up in about five minutes. This would have easily taken me 5 or 10x longer if I did it manually.

    Give me a main.go file that responds to a GET request by reading records from a local JSON file called property.json and passes the results to an existing html/template named home.html. The record should be defined in a struct with fields for ID, Name, Description, and ImageUrl.
    Create an html/template for my Go app that uses Bootstrap for styling, and loops through records. For each loop, create a box with a thin border, an image at the top, and text below that. The first piece of text is "title" and is a header. Below that is a short description of the item. Ensure that there's room for four boxes in a single row.
    Give me an example data.json that works with this struct
    Add a second function to the class that responds to HTML requests for details for a given record. Accept a record id in the querystring and retrieve just that record from the array before sending to a different html/template

    With these few prompts, I had 75% of my app completed. Wild! I took this baseline, and extended it. The final result has folders for data, personas, images, a couple HTML files, and a single main.go file.

    Let’s look at the main.go file, and I’ll highlight a handful of noteworthy bits.

    package main
    
    import (
    	"context"
    	"encoding/json"
    	"fmt"
    	"html/template"
    	"log"
    	"net/http"
    	"os"
    	"strconv"
    
    	"github.com/google/generative-ai-go/genai"
    	"google.golang.org/api/option"
    )
    
    // Define a struct to hold the data from your JSON file
    type Record struct {
    	ID          int
    	Name        string
    	Description string
    	ImageURL    string
    }
    
    type UserPref struct {
    	Name        string
    	Preferences string
    }
    
    func main() {
    
    	// Parse the HTML templates
    	tmpl := template.Must(template.ParseFiles("home.html", "details.html"))
    
    	//return the home page
    	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    
    		var recordType string
    		var recordDataFile string
    		var personId string
    
    		//if a post-back from a change in record type or persona
    		if r.Method == "POST" {
    			// Handle POST request:
    			err := r.ParseForm()
    			if err != nil {
    				http.Error(w, "Error parsing form data", http.StatusInternalServerError)
    				return
    			}
    
    			// Extract values from POST data
    			recordType = r.FormValue("recordtype")
    			recordDataFile = "data/" + recordType + ".json"
    			personId = r.FormValue("person")
    
    		} else {
    			// Handle GET request (or other methods):
    			// Load default values
    			recordType = "property"
    			recordDataFile = "data/property.json"
    			personId = "person1" // Or any other default person
    		}
    
    		// Parse the JSON file
    		data, err := os.ReadFile(recordDataFile)
    		if err != nil {
    			fmt.Println("Error reading JSON file:", err)
    			return
    		}
    
    		var records []Record
    		err = json.Unmarshal(data, &records)
    		if err != nil {
    			fmt.Println("Error unmarshaling JSON:", err)
    			return
    		}
    
    		// Execute the template and send the results to the browser
    		err = tmpl.ExecuteTemplate(w, "home.html", struct {
    			RecordType string
    			Records    []Record
    			Person     string
    		}{
    			RecordType: recordType,
    			Records:    records,
    			Person:     personId,
    		})
    		if err != nil {
    			fmt.Println("Error executing template:", err)
    		}
    	})
    
    	//returns the details page using AI assistance
    	http.HandleFunc("/details", func(w http.ResponseWriter, r *http.Request) {
    
    		id, err := strconv.Atoi(r.URL.Query().Get("id"))
    		if err != nil {
    			fmt.Println("Error parsing ID:", err)
    			// Handle the error appropriately (e.g., redirect to error page)
    			return
    		}
    
    		// Extract values from querystring data
    		recordType := r.URL.Query().Get("recordtype")
    		recordDataFile := "data/" + recordType + ".json"
    
    		//declare recordtype map and extract selected entry
    		typeMap := make(map[string]string)
    		typeMap["property"] = "Create an improved home listing description that's seven sentences long and oriented towards a a person with these preferences:"
    		typeMap["store"] = "Create an updated paragraph-long summary of this store item that's colored by these preferences:"
    		typeMap["restaurant"] = "Create a two sentence summary for this menu item that factors in one or two of these preferences:"
    		//get the preamble for the chosen record type
    		aiPremble := typeMap[recordType]
    
    		// Parse the JSON file
    		data, err := os.ReadFile(recordDataFile)
    		if err != nil {
    			fmt.Println("Error reading JSON file:", err)
    			return
    		}
    
    		var records []Record
    		err = json.Unmarshal(data, &records)
    		if err != nil {
    			fmt.Println("Error unmarshaling JSON:", err)
    			return
    		}
    
    		// Find the record with the matching ID
    		var record Record
    		for _, rec := range records {
    			if rec.ID == id { // Assuming your struct has an "ID" field
    				record = rec
    				break
    			}
    		}
    
    		if record.ID == 0 { // Record not found
    			// Handle the error appropriately (e.g., redirect to error page)
    			return
    		}
    
    		//get a reference to the persona
    		person := "personas/" + (r.URL.Query().Get("person") + ".json")
    
    		//retrieve preference data from file name matching person variable value
    		preferenceData, err := os.ReadFile(person)
    		if err != nil {
    			fmt.Println("Error reading JSON file:", err)
    			return
    		}
    		//unmarshal the preferenceData response into an UserPref struct
    		var userpref UserPref
    		err = json.Unmarshal(preferenceData, &userpref)
    		if err != nil {
    			fmt.Println("Error unmarshaling JSON:", err)
    			return
    		}
    
    		//improve the message using Gemini
    		ctx := context.Background()
    		// Access your API key as an environment variable (see "Set up your API key" above)
    		client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY")))
    		if err != nil {
    			log.Fatal(err)
    		}
    		defer client.Close()
    
    		// For text-only input, use the gemini-pro model
    		model := client.GenerativeModel("gemini-pro")
    		resp, err := model.GenerateContent(ctx, genai.Text(aiPremble+" "+userpref.Preferences+". "+record.Description))
    		if err != nil {
    			log.Fatal(err)
    		}
    
    		//parse the response from Gemini
    		bs, _ := json.Marshal(resp.Candidates[0].Content.Parts[0])
    		record.Description = string(bs)
    
    		//execute the template, and pass in the record
    		err = tmpl.ExecuteTemplate(w, "details.html", record)
    		if err != nil {
    			fmt.Println("Error executing template:", err)
    		}
    	})
    
    	fmt.Println("Server listening on port 8080")
    	fs := http.FileServer(http.Dir("./images"))
    	http.Handle("/images/", http.StripPrefix("/images/", fs))
    	http.ListenAndServe(":8080", nil)
    }
    

    I do not write great Go code, but it compiles, which is good enough for me!

    On line 13, see that I refer to the Go package for interacting with the Gemini model. All you need is an API key, and we have a generous free tier.

    On line 53, notice that I’m loading the data file based on the type of record picked on the HTML template.

    On line 79, I’m executing the HTML template and sending the type of record (e.g. property, restaurant, store), the records themselves, and the persona.

    On lines 108-113, I’m storing a map of prompt values to use for each type of record. These aren’t terrific, and could be written better to get smarter results, but it’ll do.

    Notice on line 147 that I’m grabbing the user preferences we use for customization.

    On line 163, I create a Gemini client so that I can interact with the LLM.

    On line 171, see that I’m generating AI content based on the record-specific preamble, the record details, and the user preference data.

    On line 177, notice that I’m extracting the payload from Gemini’s response.

    Finally, on line 181 I’m executing the “details” template and passing in the AI-augmented record.

    None of this is rocket science, and you can check out the whole project on GitHub.

    What an “enterprise” version might look like

    What I have here is a local example app. How would I make this more production grade?

    • Store catalog images in an object storage service. All my product images shouldn’t be local, of course. They belong in something like Google Cloud Storage.
    • Add catalog items and user preferences to a database. Likewise, JSON files aren’t a great database. The various items should all be in a relational database.
    • Write better prompts for the LLM. My prompts into Gemini are meh. You can run this yourself and see that I get some silly responses, like personalizing the message for a pillow by mentioning sporting events. In reality, I’d write smarter prompts that ensured the responding personalized item summary was entirely relevant.
    • Use Vertex AI APIs for accessing Gemini. Google AI Studio is terrific. For production scenarios, I’d use the Gemini models hosted in full-fledged MLOps platform like Vertex AI.
    • Run app in a proper cloud service. If I were really building this app, I’d host it in something like Google Cloud Run, or maybe GKE if it was part of a more complex set of components.
    • Explore whether pre-generating AI-augmented results and caching them would be more performant. It’s probably not realistic to call LLM endpoints on each “details” page. Maybe I’d pre-warm certain responses, or come up with other ways to not do everything on the fly.

    This exercise helped me see the value of AI-assisted developer tooling firsthand. And, it feels like there’s something useful about LLM summarization being applied to a variety of “boring” app scenarios. What do you think?