Building a Non-Streaming Chat App - Instruction

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Creating a Fact Checking App

A chat app, like ChatGPT, asks users for an input, responds, and allows users to send more messages in the same thread. This app takes in all the previous messages, from the user and from itself, as context for its next response. You’re going to make a similar app in this lesson.

Fetching URL Content

In the previous lesson, you mocked the response of getting the URL. Note that the starter code for this lesson already includes a real implementation of fetching the text from a webpage. Because this is not central to the lesson, you can try understanding how it’s done on your own.

Asking the User for Inputs

Because you’ll ask the user for inputs, the first thing to do is to remove the user’s initial message from the history of messages. Find the messages array and remove the message that has the role user. It should look like the code below:

SYSTEM_PROMPT = (
  "You are a fact checker. Verify the validity of the sentence provided by the user, given a reference. You must return a response in JSON format:"
  "{'isFactTrue': <true or false>, 'explanation': <explanation> }"
)
messages = [
  {"role": "system", "content": SYSTEM_PROMPT},
]
response = client.chat.completions.create(
  model=model,
  messages=messages,
  response_format={"type": "json_object"},
)
user_input = input("Please enter your input: ")
messages.append({"role": "user", "content": user_input})

{
  "isFactTrue": false,
  "explanation": "While Flutter is a popular open-source UI framework for building natively compiled applications for mobile, web, and desktop from a single codebase, stating it as 'the best' framework is subjective and depends on individual needs and preferences. There are many other frameworks available such as React Native, Xamarin, and Angular, which may be preferred by different developers depending on their project requirements."
}

Chat Loop

Now that you can ask the user for inputs, you’ll want to make the chat app ask the user again after it responds. You’ll implement this in a loop.

# 1
while True:
  # 2
  user_input = input("Please enter your input: ")

  # 3
  if user_input.lower() == 'exit':
      break

  # 4
  messages.append({"role": "user", "content": user_input})

  # 5
  # Replace the lines below with try-except
  response = client.chat.completions.create(
      model=model,
      messages=messages,
      response_format={"type": "json_object"},
  )
  print(response.choices[0].message.content)

  messages.append({"role": "assistant", "content": response.choices[0].message.content})

Error Handling

Giving your user the ability to send infinite responses to the app can lead to some currently unhandled problems. You might recall that you added error handling in an earlier lesson. You should remember to add these when performing calls to chat completion. If the user sent responses too quickly, you might receive a rate-limit error.

# 1
try:
  # 2
  response = client.chat.completions.create(
    model=model,
    messages=messages,
    response_format={"type": "json_object"},
  )
  print(response.choices[0].message.content)

  messages.append({"role": "assistant", "content": response.choices[0].message.content})
# 3
except openai.RateLimitError as e:
  print(f"Rate limit exceeded: {e}")

Tool Calls

The last part of this chat app is its ability to add content from the web to make its fact-checking more accurate.

messages.append({"role": "assistant", "content": response.choices[0].message.content})
# 1
import json

# 2
def process_response_with_tools(response):
  # 3
  response_message = response.choices[0].message
  tool_calls = response_message.tool_calls

  # 4
  if tool_calls:
    # 5
    messages.append(response_message)

    # 6
    available_functions = {
      "get_text_from_url": get_text_from_url,
    }
    # 7
    for tool_call in tool_calls:

      # 8
      function_name = tool_call.function.name
      function_to_call = available_functions[function_name]
      function_args = json.loads(tool_call.function.arguments)
      function_response = function_to_call(
        url=function_args.get("url"),
      )
      # 9
      messages.append(
        {
          "tool_call_id": tool_call.id,
          "role": "tool",
          "name": function_name,
          "content": function_response,
        }
      )
      # 10
      tool_response = client.chat.completions.create(
        model=model,
        messages=messages,
        response_format={"type": "json_object"},
      )
      messages.append({"role": "assistant", "content": tool_response.choices[0].message.content})

      return tool_response
  # 11
  else:
    messages.append({"role": "assistant", "content": response.choices[0].message.content})
    return None
# 1
try:
  # 2
  response = client.chat.completions.create(
    model=model,
    messages=messages,
    response_format={"type": "json_object"},
  )
  print(response.choices[0].message.content)

  messages.append({"role": "assistant", "content": response.choices[0].message.content})
# 3
except openai.RateLimitError as e:
  print(f"Rate limit exceeded: {e}")
try: # did not change this
  # 1
  response = client.chat.completions.create(
      model=model,
      tools=tools,
      messages=messages,
      response_format={"type": "json_object"},
    )

  # 2
  tool_response = process_response_with_tools(response)

  # 3
  if tool_response:
    print(tool_response.choices[0].message.content)
  # 4
  else:
    print(response.choices[0].message.content)
# did not change this
except openai.RateLimitError as e:
  print(f"Rate limit exceeded: {e}")
Flutter is the most popular framework https://www.statista.com/statistics/869224/worldwide-software-developer-working-hours/#:~:text=Flutter%20is%20the%20most%20popular,of%20software%20developers%20used%20Flutter.

See forum comments
Download course materials from Github
Previous: Building a Non-Streaming Chat App - Introduction Next: Building a Non-Streaming Chat App - Demo