1+ """
2+ InsecureWebApp - an insecure Python/Flask Web application
3+
4+ Copyright (C) 2024-2025 Kevin A. Lee (kadraman)
5+
6+ This program is free software: you can redistribute it and/or modify
7+ it under the terms of the GNU General Public License as published by
8+ the Free Software Foundation, either version 3 of the License, or
9+ (at your option) any later version.
10+
11+ This program is distributed in the hope that it will be useful,
12+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ GNU General Public License for more details.
15+
16+ You should have received a copy of the GNU General Public License
17+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ """
19+ import logging
20+ import os
21+ import time
22+
23+ from flask import render_template , request , jsonify , session
24+ from openai import OpenAI
25+
26+ from iwa .blueprints .assistant import assistant_bp
27+
28+
29+ logger = logging .getLogger (__name__ )
30+
31+ # Initialize the OpenAI client
32+ api_key = os .getenv ("OPENAI_API_KEY" )
33+ if api_key :
34+ logger .debug ("OPENAI_API_KEY: %s" , api_key )
35+ logger .debug ("AI Assistant functionality is enabled." )
36+ client = OpenAI (api_key = api_key )
37+ else :
38+ logger .debug ("OpenAI API key not found. Assistant functionality is disabled." )
39+
40+ # Initialize the assistant and thread globally
41+ assistant_id = ""
42+ thread_id = ""
43+
44+ # Define a global chat history
45+ chat_history = [
46+ {"role" : "system" , "content" : "You are a helpful assistant." },
47+ ]
48+
49+
50+ def create_assistant ():
51+ global assistant_id
52+ if assistant_id == "" :
53+ my_assistant = client .beta .assistants .create (
54+ instructions = """You are a helpful medical assistant. You can help with medical questions and provide
55+ information on various health topics. If you are unsure about a question, please advise the user to
56+ consult a healthcare professional. You can also help with scheduling appointments, providing information on medications,
57+ and answering general health inquiries. Always prioritize user safety and confidentiality.
58+ """ ,
59+ name = "MyMedicalAssistant" ,
60+ model = "gpt-3.5-turbo" ,
61+ tools = [{"type" : "file_search" }],
62+ )
63+ assistant_id = my_assistant .id
64+ else :
65+ my_assistant = client .beta .assistants .retrieve (assistant_id )
66+ assistant_id = my_assistant .id
67+
68+ return my_assistant
69+
70+
71+ def create_thread ():
72+ global thread_id
73+ if thread_id == "" :
74+ thread = client .beta .threads .create ()
75+ thread_id = thread .id
76+ else :
77+ thread = client .beta .threads .retrieve (thread_id )
78+ thread_id = thread .id
79+
80+ return thread
81+
82+
83+ @assistant_bp .route ('/' , methods = ['GET' , 'POST' ])
84+ def index ():
85+ """assistant page."""
86+ if not api_key :
87+ session ["assistant_enabled" ] = False
88+ message = "The AI Assistant is not currently available. Please try again later!"
89+ else :
90+ session ["assistant_enabled" ] = True
91+ message = "The AI Assistant is ready to help you!"
92+ return render_template ("assistant/index.html" , message = message )
93+
94+ @assistant_bp .route ('/chat' , methods = ['POST' ])
95+ def chat ():
96+ content = request .json ["message" ]
97+ chat_history .append ({"role" : "user" , "content" : content })
98+
99+ # Send the message to the assistant
100+ message_params = {"thread_id" : thread_id , "role" : "user" , "content" : content }
101+
102+ thread_message = client .beta .threads .messages .create (** message_params )
103+
104+ # Run the assistant
105+ run = client .beta .threads .runs .create (
106+ thread_id = thread_id , assistant_id = assistant_id
107+ )
108+ # Wait for the run to complete and get the response
109+ while run .status != "completed" :
110+ time .sleep (0.5 )
111+ run = client .beta .threads .runs .retrieve (thread_id = thread_id , run_id = run .id )
112+
113+ response = client .beta .threads .messages .list (thread_id ).data [0 ]
114+
115+ text_content = None
116+
117+ # Iterate through the content objects to find the first text content
118+ for content in response .content :
119+ if content .type == "text" :
120+ text_content = content .text .value
121+ break # Exit the loop once the first text content is found
122+
123+ # Check if text content was found
124+ if text_content :
125+ chat_history .append ({"role" : "assistant" , "content" : text_content })
126+ return jsonify (success = True , message = text_content )
127+ else :
128+ # Handle the case where no text content is found
129+ return jsonify (success = False , message = "No text content found" )
130+
131+
132+ @assistant_bp .route ('/reset' , methods = ['POST' ])
133+ def reset_chat ():
134+ global chat_history
135+ chat_history = [{"role" : "system" , "content" : "You are a helpful assistant." }]
136+
137+ global thread_id
138+ thread_id = ""
139+ create_thread ()
140+ return jsonify (success = True )
141+
142+ @assistant_bp .route ("/get_ids" , methods = ["GET" ])
143+ def get_ids ():
144+ return jsonify (assistant_id = assistant_id , thread_id = thread_id )
145+
146+ @assistant_bp .route ("/get_messages" , methods = ["GET" ])
147+ def get_messages ():
148+ if thread_id != "" :
149+ thread_messages = client .beta .threads .messages .list (thread_id , order = "asc" )
150+ messages = [
151+ {
152+ "role" : msg .role ,
153+ "content" : msg .content [0 ].text .value ,
154+ }
155+ for msg in thread_messages .data
156+ ]
157+ return jsonify (success = True , messages = messages )
158+ else :
159+ return jsonify (success = False , message = "No thread ID" )
160+
161+ @assistant_bp .before_request
162+ def before_request ():
163+ if api_key :
164+ create_assistant ()
165+ create_thread ()
166+
167+ @assistant_bp .after_request
168+ def after_request (response ):
169+ return response
0 commit comments