Photo by CA Creative on Unsplash

With Flutter and PaLM API to Instant Wine Expertise 🍷

Sylvia Dieckmann
10 min readSep 18, 2023

--

Can a Flutter app take advantage of the powers of generative AI? In this article, I show how PaLM API can be combined with Flutter to build an app that generates polished tasting notes from just the title of the wine.

The resulting tasting notes are very well written but are they hitting the mark? Does the LLM have enough data to reason about a sensory experience? In part 2 [TBD] I have a closer look at the quality of the results.

Motivation

Like many tech companies, Google is currently putting a lot of resources into making generative AI more accessible for us developers. Their efforts include PaLM 2, the latest and most powerful large language model (LLM), as well as the corresponding access library PaLM API.

In addition, the web-based MakerSuite tool helps to prototype generative AI applications via a web interface. Developers can use MakerSuite to explore different models and refine their prompts before going through the motions of building their apps.

To invite the developer community to the party, Google’s product team recently called for a PaLM API/MakerSuite sprint. The challenge they put down for the developer community: explore the new tools and develop creative app ideas around generative AI. I love a good challenge and so I jumped at this opportunity to try my hands on this (for me) new tech.

The App Idea

I live in the Cape Winelands, a South African district known for excellent wines, and so the wine theme frequently features in my demo apps. In this case, I decided to use PaLM API to generate realistic-sounding tasting notes from a short wine label or description.

Next, the PaLM API prompt should be integrated into a bespoke Flutter app which I lovingly titled “WineSnob”.

Disclaimer: In my family “wine snob” is not an insult but an endearing (albeit slightly tongue-in-cheek) label used for anybody who enjoys wines.🍷

The idea: you enter some information about a wine you are interested in, like vintage, grape variety, and name. The app then returns a description of the wine in the style of a wine critic.

Input: Meerlust Rubicon 2015

Output:
The 2015 Meerlust Rubicon is a deep, dark purple wine with a brooding nose of
black fruit, cassis, plum, incense, and liquorice. It is still very tightly
coiled, slowly offering cigar box, crushed stone, and subtle oak spice. On
the palate, the wine is concentrated yet restrained, with dark fruit flavors
of pastille, mulberry, and dark chocolate, all held in an intricate lattice
of polished, sleek grape tannin. The finish is long and lingering, with a
hint of minerality.

This is a superb wine that is still young, but already showing great promise.
It is a classic example of this iconic South African wine, and is sure to
please fans of Cabernet Sauvignon and Bordeaux-style blends.

Pair with: Slow-cooked beef ribs, sautéed wild mushrooms and venison steak, or
garlic pork rib roast.

Part 1: Designing the Prompt

Anybody who plays around with a chat-style generative LLM such as Bard or ChatGPT quickly comes across examples where the bot fails. Ask Bard to compose a poem and the result is likely clumsy and non-sensical. However, the responses can often be improved by carefully crafting the question and by adding context and examples. This is called prompt engineering. A good prompt is crucial for the success of any AI-supported app.

MakerSuite makes the process of designing and refining a prompt very easy. It allows you to test out and prototype LLM prompts straight from your browser. Once the prompt is configured to your satisfaction you can use MakerSuite to generate code which can be imported straight into your app.

MakerSuite supports three different prompt styles. For each style, it provides a number of preconfigured examples that can be copied and customized to support new use cases.

The three styles of MakerSuite prompts are:

  1. Text prompt
    Free-form experiments with optional examples to provide additional guardrails.
  2. Data prompt
    Input/output examples are provided in tabular form.
  3. Chat prompt
    Conversational experiences

Designing WineSnob Prompts

For the purpose of this project, I used MakerSuite to design a number of prompts that would generate tasting notes just from a Wine’s name and vintage. My aim was to generate tasting notes that appeared well-written and artistic. Correctness came second.

I tried out all three interfaces. In each round, I tested my prompt with a number of local wines. As inputs, I used titles from Joostenberg, a South African boutique wine estate specializing in organic wines.

  • 2015 Joostenberg Bakermat. This is Joostenberg’s flagship red blend. The web shop currently sells the 2018 vintage but older vintages are still available.
  • 2022 Joostenberg Chenin Blanc. A young single variety white wine designed for easy drinking.
  • 2017 Joostenberg Opgemaakte Naam. This is not a real wine and so it’s called “made-up name” in Afrikaans. Will the model spot the trap?

Text Prompt

After a bit of trial and error I ended up with a pretty text simple prompt. The beauty of this prompt was that I only had to describe the desired outcome without giving concrete examples.

{
"prompt": "Write tasting notes for the 2015 Joostenberg Bakermat. The tasting notes should be in the style of a wine critic and should mention the wine's style, taste, and production process. Keep the response to a single paragraph.",
"model_name": "models/text-bison-001",
"temperature": 0.7,
"candidate_count": 1,
"top_k": 40,
"top_p": 0.95,
"max_output_tokens": 1024,
"stop_sequences": [],
"safety_settings": [{"category":"HARM_CATEGORY_DEROGATORY","threshold":1},{"category":"HARM_CATEGORY_TOXICITY","threshold":1},{"category":"HARM_CATEGORY_VIOLENCE","threshold":2},{"category":"HARM_CATEGORY_SEXUAL","threshold":2},{"category":"HARM_CATEGORY_MEDICAL","threshold":2},{"category":"HARM_CATEGORY_DANGEROUS","threshold":2}]
}

Data Prompt

For the data prompt, I gave some instructions regarding the style of my answers and a few examples of input and output. To keep it simple, I chose some actual wines from the region but avoided including Joostenberg examples for fear of overfitting.

{
"prompt": "Write tasting notes for the given wine. The tasting notes should be in the style of a wine critic and should mention the wine style, taste, and production process. Keep the response to a single paragraph.\ninput: 2018 La Motte Syrah\noutput: La Motte Syrah red wine is a true expression of its Franschhoek terroir where micro-climates from the mountain slopes and valley floors add complexity to the wine’s elegant character. Syrah wine from Franschhoek contains a natural fruitiness that includes red berries and mulberry, while a small percentage Durif provides colour, plum fruit and texture.\n\nThe full-bodied character of this red wine harmonises perfectly with rich, flavourful dishes, grilled foods (including grilled vegetables), game dishes (particularly those incorporating stewed fruit and sweet aromatic spice components), peppercorn-crusted steaks and barbecued meat in a sticky, sweet sauce. The red wine’s abundant fruit also latches onto the sweetness in jellies, chutneys and berry sauces.\ninput: 2022 Kleine Zalze Chenin Blanc\noutput: Flavours of melon, white peach and almond blossom and a hint of minerality that adds to the elegance of the wine. Masterfully oaked, this wine is textured and creamy on the mid-palate with a lively, crisp finish. This wine can be enjoyed now, but with careful cellaring it should age gracefully over the next 10 years.\ninput: ${description}\noutput:",
"model_name": "models/text-bison-001",
"temperature": 0.7,
"candidate_count": 1,
"top_k": 40,
"top_p": 0.95,
"max_output_tokens": 1024,
"stop_sequences": [],
"safety_settings": [{"category":"HARM_CATEGORY_DEROGATORY","threshold":1},{"category":"HARM_CATEGORY_TOXICITY","threshold":1},{"category":"HARM_CATEGORY_VIOLENCE","threshold":2},{"category":"HARM_CATEGORY_SEXUAL","threshold":2},{"category":"HARM_CATEGORY_MEDICAL","threshold":2},{"category":"HARM_CATEGORY_DANGEROUS","threshold":2}]
}

Chat Prompt

The chat prompt is the most complex of the three as it requires anticipating a longer sequence. I didn’t think this style was appropriate for my purpose but since the Haiku Generator code lab (described further down) uses a chat prompt, I gave it a try and the results were decent.

{
"model_name": "models/chat-bison-001",
"context": "You are a wine expert who has just tasted a wine. You are asked to describe the style and aroma in one paragraph.",
"examples": [
[
"What can you say about the Kleine Zalze chenin blanc\nBarrel Fermented 2022",
"Flavours of melon, white peach and almond blossom and a hint of minerality that adds to the elegance of the wine. Masterfully oaked, this wine is textured and creamy on the mid-palate with a lively, crisp finish. This wine can be enjoyed now, but with careful cellaring it should age gracefully over the next 10 years."
]
],
"messages": [
"Describe the 2018 La Motte Syrah",
"The 2018 La Motte Syrah is a full-bodied, powerful wine with intense black fruit flavors of blackberry, blackcurrant, and plum. The wine is also characterized by its spicy, peppery notes and its firm tannins. The 2018 La Motte Syrah is a wine that will age well for many years and is best enjoyed with grilled meats or hearty stews.\n\nThe 2018 La Motte Syrah was produced from grapes grown in the Stellenbosch region of South Africa. The grapes were hand-harvested and fermented in small stainless steel tanks. The wine was then aged in French oak barrels for 18 months.\n\nThe 2018 La Motte Syrah is a wine that is sure to please fans of full-bodied, powerful red wines. The wine is well-balanced and has a long, lingering finish. The 2018 La Motte Syrah is a wine that is sure to impress your guests.\n\nHere is a more detailed description of the wine's aroma and flavor:\n\nThe nose of the wine is dominated by black fruit flavors, such as blackberry, blackcurrant, and plum. There are also hints of spice, such as black pepper and cloves. The wine's palate is full-bodied and powerful, with flavors of black fruit, spice, and earth. The wine's tannins are firm but well-integrated, and the wine's finish is long and lingering.\n\nThe 2018 La Motte Syrah is a wine that is best enjoyed with grilled meats or hearty stews. The wine can also be cellared for many years and will continue to develop complexity with age.",
"Is the 2018 La Motte Syrah a red or a white wine?",
"The 2018 La Motte Syrah is a red wine. Syrah is a red wine grape variety that is grown in many parts of the world, including Australia, France, Italy, and the United States. Syrah wines are typically full-bodied and have flavors of black fruit, spice, and earth. They can be aged for many years and will continue to develop complexity with age.",
"NEXT REQUEST"
],
"temperature": 0.25,
"candidate_count": 1,
"top_k": 40,
"top_p": 0.95
}

Overall, all three styles returned decent results. My only complaint with all three was that the results were sometimes formatted as multiple paragraphs or bullet point lists despite my instructions to answer with a single paragraph.

To determine the best prompt would require a much deeper analysis and will be left for another time.

Part 2: Flutter Integration

This part was a lot easier than I had expected, especially once I found Google’s PaLM API/Flutter code lab. In this code lab, you learn to develop a haiku generator in Flutter using PaLM API and a chat prompt. You start by setting up a list of Google products as a dropdown menu. On selecting a product, the selection is added to a preconfigured prompt and sent to the Palm API via HTTP request. The view is then updated to display the generated haikus.

After going through the code lab I just had to change the input screen to accept free text. Next, I needed to update the prompt to reflect what I had tested in part 1. Finally, I needed to get my own API key in MakerSuite.

The resulting app was immediately functional albeit a bit simplistic. I wanted to push it a bit further, so I refactored the codelab-based app to better suit my architectural style. (My apps usually use RiverPod for state management and borrow heavily from the starter architecture advocated by Andrea Bizzotto.)

I also added Firebase authentication and Firestore because I wanted to give users the opportunity to play around with different preconfigured prompt styles. Since I was particularly interested in evaluating the quality of the results, I wanted to give users the opportunity to save and critique their results. This was easily accomplished with a Firestore backend.

You can check out the code at https://github.com/githubmonkey/wine_snob or play with the app at https://winesnob.rozendallabs.org/

Conclusions

Integrating PaLM API into Flutter is dead easy and I am looking forward to a lot more (and more serious) AI-enhanced Flutter apps. But in addition to the technical challenges, this experiment also shows the power and limitations of the current crop of generative AI models.

Wine lovers will agree that the descriptions generated by my tool were well-written and realistic. On closer inspection though, some problems appeared. Most results contain some truths, but also some doubtful statements. To spot the errors hidden in such professional-sounding copy would be impossible for all but the most knowledgeable wine critics.

Future work

In part two of this article, I will meet with a wine expert to have a closer look at some of the responses generated by the app. The question we will tackle: Can a soulless tool that understands language and knows a lot about the world, but that doesn’t have a palate, still manage to impress the expert?

--

--