Showing posts with label Google. Show all posts
Showing posts with label Google. Show all posts

Wednesday, September 3, 2025

Google API

To experiment with LLMs I chose to use Gemini. The cost is modest and I expect Google to regularly improve the model so that it remains competitive. I wrote a Gemini client in Common Lisp. Some people have already forked the repo, but I've refactored things recently so I thought I'd give a quick rundown of the code.

google repository

https://github.com/jrm-code-project/google

When I add APIs to Google, I intend to put them in this repository. It is pretty empty so far, but here is where they will go. Contributions welcome.

Basic Requirements

There are some basic libraries you can load with Zach Beane's Quicklisp. alexandria for some selected Common Lisp extensions, cl-json for JSON parsing, dexador for HTTP requests, and str for string manipulation. I also use series (available from SourceForge). My own fold, function, named-let, and jsonx libraries are also used (available from GitHub).

fold gives you fold-left for list reduction. function gives you compose. jsonx modifies cl-json to remove the ambiguity betweeen JSON objects and nested arrays. named-let gives you the named let syntax from Scheme for local iteration and recursion.

Google API

The google repository contains the beginnings of a Common Lisp client to Google services. It currently only supports an interface to Blogger that can return your blog content as a series of posts and an interface to Google's Custom Search Engine API. You create a Google services account (there is a free tier, and a paid tier if you want more). You create a project (you'll want at least a default project), and within that project you enable the Google services that you want that project to have access to.

API Keys and Config Files

For each service you can get an API key. In your XDG config directory (usually "~/.config/") you create a googleapis directory and subdirectories for each project you have created. The ~/.config/googleapis/default-project file contains the name of your default project. In the examples below, it contains the string my-project.

Within each project directory you create subdirectories for each service you want to use. In each service directory you create a file to hold the API key and possibly other files to hold IDs, options, and other config information. For example, for Blogger you create ~/.config/googleapis/my-project/Blogger/apikey to hold your Blogger API key and ~/.config/googleapis/my-project/Blogger/blog-id to hold your blog ID.

Here is a sample directory structure:

  ~/.config/googleapis/
    ├── my-project/
    │   ├── Blogger/
    │   │   ├── apikey
    │   │   └── blog-id
    │   ├── CustomSearchEngine/
    │   │   ├── apikey
    │   │   ├── hyperspec-id
    │   │   └── id
    │   └── Gemini/
    │       └── apikey
    └── default-project

When you create the API keys for the various services, it is a good idea to restrict the API key for only that service. That way, if the API key is compromised, the damage is limited to a single service.

Blogger

The blogger API will eventually have more features, but it currently only allows you to get the posts from a blog as a series.

scan-blogger-posts blog-id
Returns a series of posts from the blog with the given ID. Each post comes back as a JSON object (hash-table). The :content field contains the HTML content of the post.

Custom Search Engine

The Custom Search Engine API allows you to search a set of web pages. You create a search engine on Google and pass the ID custom-search. It is assumed that the default CustomSearchEngine id is a default, vanilla search, and that the hyperspec id searches the Common Lisp Hyperspec.

In each search, be sure to replace the spaces in the query with plus signs (+) before searching.

custom-search query &key custom-search-engine-id
Returns search results for query. Each search result comes back as a JSON object (hash-table).

web-search query
Search the web and return search results for query. Each search result comes back as a JSON object (hash-table).

hyperspec-search query
Search the Common Lisp Hyperspec and return search results for query. Each search result comes back as a JSON object (hash-table).


Friday, April 11, 2025

Bloom Filter

This is the response time of the Google Mini search appliance on several thousand queries. There is an odd spike at 300 ms. A number of machines were taking exactly 300 ms to respond regardless of the query.

I soon tracked this down to the spell server. This is the microservice that puts “Did you mean foobar?” on the top of the page when you spell something wrong. The results page generator will wait up to 300 ms for the spell server to come up with its suggestions and then it will proceed without it. What appeared to be happening is that the spell server was giving a “no go” signal to the page generator at the beginning of page composition. The results page generator would then wait for the spell server to make a suggestion. The spell server would invariably take too long, so after 300 ms, the results page generator would time out and ship the page as is. This happened often enough that it showed up as a blip in the performance graph.

The spell server was based on a Bloom filter. A Bloom filter is a variation on a hash table where you only record that a bucket exists, but not its contents. A Bloom filter will quickly and reliably tell you if an entry is not in the table, but only probabilistically tell you if an entry is in the table. Bloom filters rely on having a good hash function and having a mostly empty hash table. If the hash table is mostly empty, the Bloom filter will usually end up hitting an empty bucket and returning false immediately.

A quick look at the spellserver showed that the Bloom filter was almost always getting a hit, this would send the “no go” signal and trigger a slow lookup to find the misspelled word. The problem was that the Bloom filter was too small. It had too few buckets, so most buckets had an entry. Words would always get a hit in the Bloom filter and so the search appliance thought that all words were misspelled.

I adusted the size of the Bloom filter, giving it several million buckets. Now correctly spelled words would likely hit an empty bucket and the filter would give a “go” signal to the response page generator. Problem solved, and the spike at 300 ms went away.


Thursday, May 16, 2024

Readability at Google

Over the years I was a developer at Google I never once tried to pass “readability” for any language. If you didn’t have “readability”, then any code you checked in would need an additionally review by someone who did have “readability”. The theory was that the code base would turn into an unreadable patchwork of different styles if everyone didn't adhere to the same set of rules. By having a “readability” requirement, the code base would be uniform and understandable. In practice, however, it was a social signal that indicated whether you were a card carrying member of the “in” group or not. Having “readability” meant you were a nobleman. Not having it meant you were a commoner.

To get “readability” you had to endure a struggle session with a current holder of “readability”. You would submit a not insubstantial amount of code for review and the reviewer would go over it with a fine-tooth comb pointing out every little syntactic rule you broke. It was a game of gotcha designed to make the reviewer feel smarter than you. You’d then return to your office or cubicle, make changes and iterate. If you were lucky, you would only need two or three iterations before you were bestowed with “readability”. The point was not to demonstrate that you knew how to write readable code, but to demonstrate that you were willing to submit to the authority of the reviewer and follow a set of arbitrary rules, no matter how absurd. It was a hazing ritual, a way to show that you were willing to be a team player.

A problem with having “readability” was that you were expected to uphold the “readability” guidelines. Not only did you have to play the game, you had to perpetuate it. I disagreed with a lot of the guidelines because they were poorly thought out rules for the sake of having rules. There were many situations in which they would reduce the comprehensibility of the code. By not having “readability”, I was free to write code that was easier to understand and maintain, even if bent or broke the codified rules.

This isn’t to say that I ignored Google’s style. It is hard to understand code that switches styles every few lines. I tried to make my code fit in to the surrounding code and look like it was part of it. I wrote new files with same general layout, curly brace conventions, and indentation that a typical Google file has. I didn’t worry about following “readability” guidelines at all, but I didn’t flout the guidelines either. I more concerned about my code being comprehended by the next developer than following a set of ad hoc rules to the letter.

So I got used to submitting my code for “readability” review, in addition to the normal code review. I off-loaded the entire responsibility of “readability” to the reviewer and let them tell me what to do. I didn’t argue with them. I simply followed the directions of the reviewer and made whatever changes were suggested. Often, though, changes to the code to more strictly follow the guidelines would result in noticeably worse code and the reviewers would soon withdraw their suggestions.

Another problem of being a nobleman with “readability” is that you had the obligation to review the code written by the commoners. The people with “readability” was a small enough group that they soon became the bottleneck in the review process. They were constantly overworked with code reviews. We commoners, on the other hand, weren’t expected to review code. Nor were we to blame if someone else is holding up the code review.

Frankly, I didn’t see any upside of having “readability” and many downsides. I was able to get my code checked in without too much trouble and I just didn’t have the time or inclination to get involved in the high-school politics of “readability”. Plenty of other companies do not have a “readability” ritual. They seem to get along just fine by hiring people who can write code that is easy to understand and maintain.