Assistants API - USER thread is out of sync with Assistant

I’m trying to display messages as they come back from API, and allow for follow up query. However my initial query is displayed (USER) but the Assistant is not. When I ask follow up question, the response from the previous question appears. Is there an issue with my logic, or my implementation or both.

app.py

import os
import openai
from flask import Flask, render_template, request, jsonify
from dotenv import load_dotenv
import time
import re

Load environment variables from .env file

load_dotenv()

app = Flask(name)
openai.api_key = os.getenv(“OPENAI_API_KEY”)
assistant_id = os.getenv(“OPENAI_ASSISTANT_ID”)

Initialize OpenAI client

client = openai.OpenAI()

Global variable to store thread ID

thread_id = None

def clean_api_text(api_text):
pattern = re.compile(r"[TextContentBlock(text=Text(annotations=, value=‘(.*?)’), type=‘text’)]“)
cleaned_text = re.sub(pattern, r’\1’, str(api_text))
cleaned_text = cleaned_text.strip(”'")
return cleaned_text

@app.route(‘/’)
def index():
return render_template(‘index.html’)

@app.route(‘/ask’, methods=[‘POST’])
def ask():
global thread_id
data = request.json
question = data.get(‘question’)

if thread_id is None:
    thread = client.beta.threads.create()
    thread_id = thread.id

active_runs = client.beta.threads.runs.list(thread_id=thread_id).data
if active_runs and active_runs[-1].status not in ['completed', 'failed', 'incomplete']:
    return jsonify({"error": "An existing run is still active. Please wait until it completes before asking a new question."}), 400

client.beta.threads.messages.create(
    thread_id=thread_id,
    role="user",
    content=question
)

run = client.beta.threads.runs.create(
    thread_id=thread_id,
    assistant_id=assistant_id
)

return jsonify({"thread_id": thread_id, "run_id": run.id})

@app.route(‘/poll_status’, methods=[‘GET’])
def poll_status():
global thread_id
thread_id = request.args.get(‘thread_id’, thread_id)
if not thread_id:
return jsonify({“status”: “No active thread”})

run = client.beta.threads.runs.list(thread_id=thread_id).data[-1]
run_status = run.status

while run_status == 'incomplete':
    time.sleep(2)
    run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
    run_status = run.status

messages = client.beta.threads.messages.list(thread_id=thread_id).data

response_messages = []
for msg in messages:
    timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(msg.created_at))
    role = "Assistant" if msg.role == 'assistant' else "User"
    content = clean_api_text(msg.content)

    formatted_message = f"### **{role}** ({timestamp}):<br>{content}"
    response_messages.append(formatted_message)

return jsonify({"status": run.status, "messages": response_messages})

@app.route(‘/new_conversation’, methods=[‘POST’])
def new_conversation():
global thread_id
thread_id = None
return jsonify({“status”: “New conversation started”})

if name == ‘main’:
app.run(debug=True, host=‘0.0.0.0’, port=5001)

index.html

Math Tutor body { margin: 0; padding: 0; font-family: Arial, sans-serif; } .container { display: flex; flex-direction: column; height: 100vh; overflow: hidden; } .content { flex: 1; overflow-y: auto; padding: 20px; } .footer { padding: 10px; background-color: #f1f1f1; text-align: center; } .processing { display: none; color: red; } .response { white-space: pre-wrap; max-height: 300px; overflow-y: auto; background-color: #f0f8ff; padding: 10px; border-radius: 5px; } .message { margin-bottom: 10px; } .user-message { text-align: left; color: blue; } .assistant-message { text-align: right; color: green; }

Welcome to Math Tutor

Ask a math question: Ask
Processing your request...
New Conversation

© 2024 Math Tutor

document.getElementById('questionForm').addEventListener('submit', async function(event) { event.preventDefault(); const question = document.getElementById('question').value; const responseDiv = document.getElementById('response'); const processingDiv = document.getElementById('processing'); const newConversationButton = document.getElementById('new-conversation-button');
        // Clear the input field and display the processing message
        document.getElementById('question').value = '';
        processingDiv.style.display = 'block';

        const response = await fetch('/ask', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ question })
        });
        const data = await response.json();

        if (data.error) {
            responseDiv.innerHTML = data.error;
            processingDiv.style.display = 'none';
            return;
        }

        let status = 'incomplete';
        while (status === 'incomplete') {
            const statusResponse = await fetch(`/poll_status?thread_id=${data.thread_id}`);
            const statusData = await statusResponse.json();
            status = statusData.status;
            if (status !== 'incomplete') {
                responseDiv.innerHTML = statusData.messages.map(msg => `<div class="message ${msg.includes('**User**') ? 'user-message' : 'assistant-message'}">${msg}</div>`).join('');
                processingDiv.style.display = 'none';
                newConversationButton.style.display = 'inline';
            }
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    });

    document.getElementById('new-conversation-button').addEventListener('click', async () => {
        const responseDiv = document.getElementById('response');
        responseDiv.innerHTML = '';
        document.getElementById('new-conversation-button').style.display = 'none';
        await fetch('/new_conversation', { method: 'POST' });
    });
</script>

Sample Output:

User (2024-06-02 23:45:16):

What is capital of France?

Assistant (2024-06-02 23:45:04):

The answer to 2 + 2 is 4.

User (2024-06-02 23:45:00):

what is 2+2

I dont get this “”“### Assistant (2024-06-02 23:45:04):
The answer to 2 + 2 is 4.”"

Until I submit this

User (2024-06-02 23:45:16):

What is capital of France?"