Overview

9 Creating an AI-powered application

This chapter introduces how to build an AI-powered Streamlit application by creating Fact Frenzy, a trivia game that uses a Large Language Model to generate questions, evaluate free-text answers, and add personality to the game experience. The app demonstrates how LLMs can replace traditional hand-built trivia databases and rigid multiple-choice logic by producing questions on demand and interpreting user responses. It also shows how to connect Python code to OpenAI through an API key, wrap LLM interactions in a reusable class, and keep prompts separate from application logic for easier maintenance and experimentation.

A major focus is making LLM responses usable inside a real application. The chapter explains prompt design, system and user messages, and the need for structured, machine-readable outputs when the app must act on an AI response rather than merely display it. To evaluate answers reliably, the app uses a Pydantic schema with OpenAI Structured Outputs so the LLM returns fields such as whether an answer is correct and what the correct answer is. The chapter also addresses practical LLM behavior, including response variability, repeated questions, temperature, top-p, random seeds, previously asked questions, hallucinations, and cost considerations.

The chapter then develops Fact Frenzy into a complete Streamlit game by managing sequential state with a central Game class and st.session_state. It walks through solving rerun-related bugs, cycling through game states, displaying spinners during LLM calls, tracking score, adding a New Game button, supporting multiple questions, and ending the game with a final score. Finally, it adds user-configurable settings with st.data_editor and st.popover, letting players choose difficulty and a quizmaster personality that the LLM mimics in its questions, resulting in a more polished and entertaining AI-powered Streamlit app.

A UI sketch of Fact Frenzy
The flow of logic in our AI-based trivia game
Creating a secret key in your OpenAI account.
The app can now successfully call the OpenAI API to obtain a trivia question (see chapter_09/in_progress_01 in the GitHub repo for the full code).
A problem with session state causes our answer to be matched with the wrong question (see chapter_09/in_progress_02 in the GitHub repo for the full code).
Our game consists of four sequential states.
Conditional branching in the frontend based on the game's state.
The question-answer mismatch problem has been resolved (see chapter_09/in_progress_03 in the GitHub repo for the full code).
Keeping score, a New Game button, and Game Over (see chapter_09/in_progress_04 in the GitHub repo for the full code).
How temperature and top_p affect the creativity and predictability of an LLM's output.
To implement multiple questions, we now cycle through the game states in a loop.
A working multi-question trivia game (see chapter_09/in_progress_05 in the GitHub repo for the full code).
A simple output of st.data_editor.
st.data_editor with one of the columns showing a SelectBoxColumn.
A final version of Fact Frenzy with editable settings (see chapter_09/in_progress_06 in the GitHub repo for the full code).

Summary

  • A Large Language Model (LLM) is an AI system designed to process and generate human-like text.
  • LLMs can perform both creative and analytical tasks.
  • OpenAI, one of the most popular LLM providers, allows developers to access its GPT series through an API.
  • The openai library provides a convenient way to call the OpenAI API in Python.
  • You can pass a conversation to OpenAI API's chat completion endpoint with messages tagged as "system", "assistant" or "user", causing the model to complete the conversation in a logical way.
  • Structured Outputs is a feature provided by OpenAI that ensures the model will generate a response that adheres to a given schema.
  • A common pattern in linear Streamlit apps is to implement conditional branching logic based on a variable that's held in st.session_state.
  • You can vary parameters such as temperature and top_p to affect the creativity and predictability of responses generated by an LLM.
  • Injecting randomness into the prompt is a good way to ensure we get different responses to similar prompts.
  • It's important to optimize cost in LLM-based applications. You can do this by having the LLM process fewer input and output tokens, reducing the number of prompts, using cheaper models, or even having users bear the cost by requiring them to supply their own API key.
  • st.data_editor provides a way to create editable tables in Streamlit apps.
  • st.column_config lets you configure columns to be of certain editable and non-editable types in st.data_editor and st.dataframe.
  • st.popover displays a small pop-up screen triggered by a click on an associated button.

FAQ

What is Fact Frenzy?Fact Frenzy is an AI-powered trivia game built with Streamlit. It uses a Large Language Model (LLM) to generate trivia questions, accept free-text answers, evaluate whether those answers are correct, provide the correct answer when needed, track the player’s score, and optionally ask questions in different quizmaster styles.
Why is an LLM useful for a trivia game?An LLM is useful because it can generate diverse trivia questions on the fly, evaluate open-ended free-text answers instead of requiring multiple-choice responses, and add entertainment value by mimicking different speaking styles. In Fact Frenzy, the LLM acts as question generator, answer evaluator, and quizmaster personality.
How does the app connect to OpenAI from Python?The app uses OpenAI’s Python library. After installing it with pip install openai, the code creates an OpenAI client with an API key, builds a list of prompt messages, and calls the chat completions endpoint using a model such as gpt-5.1. The API key is stored safely in Streamlit’s .streamlit/secrets.toml file.
What are system, user, and assistant messages in an LLM prompt?Prompt messages include a role and content. A system message sets instructions or behavior for the model, such as “You are a quizmaster.” A user message contains the actual request from the user or app. An assistant message represents a model response, though this chapter mainly uses system and user messages.
Why does the chapter create an Llm class?The Llm class encapsulates all communication with the external LLM. This keeps OpenAI-specific logic separate from the rest of the app, making the code easier to maintain, test, and potentially modify later if a different LLM provider or model is used.
What are Structured Outputs and why are they needed?Structured Outputs ensure that the LLM responds in a predictable, schema-based format that the app can parse reliably. Fact Frenzy uses a Pydantic model called AnswerEvaluation with fields such as is_correct and correct_answer, so the app can easily decide whether to increment the score and what feedback to display.
Why did the app initially evaluate the player’s answer against the wrong question?The mismatch happened because Streamlit reruns the entire script whenever the user interacts with a widget. When the player clicked “Submit,” the app reran from the top and generated a new question before evaluating the answer. The fix was to store the game object and current question in st.session_state so the same question persists across reruns.
How does Fact Frenzy manage game state?The app uses a Game class with a status attribute representing sequential states such as GET_QUESTION, ASK_QUESTION, EVALUATE_ANSWER, and STATE_RESULT. The frontend branches based on this status and uses st.session_state to preserve the same Game instance across Streamlit reruns.
How does the app support multiple questions without repeating them?The app stores previously asked questions in a list and includes them in the prompt so the LLM can avoid repeating them. It also modifies model behavior using prompt engineering, a random seed based on the current timestamp, and parameters such as temperature and top_p to increase response variety.
How are quizmaster personalities and difficulty settings added?The app adds editable settings using st.data_editor inside an st.popover. The settings include a Quizmaster option, such as Alex Trebek, Eminem, Gollum, or Gruk the Caveman, and a Difficulty option, such as Easy, Medium, or Hard. These values are inserted into the LLM prompt so generated questions match the selected style and difficulty.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Build Python Web Apps with Streamlit ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Build Python Web Apps with Streamlit ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Build Python Web Apps with Streamlit ebook for free