3
3
from flask .views import View
4
4
import os
5
5
6
+ from backend .tenantfirstaid .session import TenantSessionData
7
+
6
8
API_KEY = os .getenv ("OPENAI_API_KEY" , os .getenv ("GITHUB_API_KEY" ))
7
9
BASE_URL = os .getenv ("MODEL_ENDPOINT" , "https://api.openai.com/v1" )
8
10
MODEL = os .getenv ("MODEL_NAME" , "o3" )
@@ -38,6 +40,66 @@ def __init__(self):
38
40
def get_client (self ):
39
41
return self .client
40
42
43
+ def prepare_developer_instructions (self , current_session : TenantSessionData ):
44
+ # Add city and state filters if they are set
45
+ instructions = DEFAULT_INSTRUCTIONS
46
+ instructions += f"\n The user is in { current_session ['city' ]} { current_session ['state' ].upper ()} .\n "
47
+ return instructions
48
+
49
+ def prepare_openai_tools (self , current_session : TenantSessionData ):
50
+ VECTOR_STORE_ID = os .getenv ("VECTOR_STORE_ID" )
51
+ if not VECTOR_STORE_ID :
52
+ return None
53
+
54
+ # We either want to use both city and state, or just state.
55
+ # This filters out other cities in the same state.
56
+ # The user is gated into selecting a city in Oregon so we don't worry about
57
+ # whether the relevant documents exist or not.
58
+ return [
59
+ {
60
+ "type" : "file_search" ,
61
+ "vector_store_ids" : [VECTOR_STORE_ID ],
62
+ "max_num_results" : os .getenv ("NUM_FILE_SEARCH_RESULTS" , 10 ),
63
+ "filters" : {
64
+ "type" : "or" ,
65
+ "filters" : [
66
+ {
67
+ "type" : "and" ,
68
+ "filters" : [
69
+ {
70
+ "type" : "eq" ,
71
+ "key" : "city" ,
72
+ "value" : current_session ["city" ],
73
+ },
74
+ {
75
+ "type" : "eq" ,
76
+ "key" : "state" ,
77
+ "value" : current_session ["state" ],
78
+ },
79
+ ],
80
+ }
81
+ if current_session ["city" ] != "null"
82
+ else None ,
83
+ {
84
+ "type" : "and" ,
85
+ "filters" : [
86
+ {
87
+ "type" : "eq" ,
88
+ "key" : "city" ,
89
+ "value" : "null" ,
90
+ },
91
+ {
92
+ "type" : "eq" ,
93
+ "key" : "state" ,
94
+ "value" : current_session ["state" ],
95
+ },
96
+ ],
97
+ },
98
+ ],
99
+ },
100
+ }
101
+ ]
102
+
41
103
42
104
class ChatView (View ):
43
105
client = OpenAI (
@@ -47,94 +109,26 @@ class ChatView(View):
47
109
48
110
def __init__ (self , tenant_session ):
49
111
self .tenant_session = tenant_session
112
+ self .chat_manager = ChatManager ()
50
113
51
114
def dispatch_request (self ):
52
115
data = request .json
53
116
user_msg = data ["message" ]
54
117
55
- # Get or create session ID using Flask sessions
56
- session_id = self .tenant_session .get_flask_session_id ()
57
-
58
118
current_session = self .tenant_session .get ()
59
119
60
- # Format messages for the new Responses API
61
- input_messages = []
62
-
63
- # Add conversation history (excluding system prompt)
64
- for msg in current_session ["messages" ][0 :]:
65
- input_messages .append ({"role" : msg ["role" ], "content" : msg ["content" ]})
66
-
67
- # Add current user message
68
- input_messages .append ({"role" : "user" , "content" : user_msg })
69
-
70
120
# Update our cache with the user message
71
121
current_session ["messages" ].append ({"role" : "user" , "content" : user_msg })
72
122
73
- # Add city and state filters if they are set
74
- instructions = DEFAULT_INSTRUCTIONS
75
- instructions += f"\n The user is in { current_session ['city' ]} { current_session ['state' ].upper ()} .\n "
76
-
77
- # We either want to use both city and state, or just state.
78
- # This filters out other cities in the same state.
79
- # The user is gated into selecting a city in Oregon so we don't worry about
80
- # whether the relevant documents exist or not.
81
- VECTOR_STORE_ID = os .getenv ("VECTOR_STORE_ID" )
82
-
83
- tools = (
84
- [
85
- {
86
- "type" : "file_search" ,
87
- "vector_store_ids" : [VECTOR_STORE_ID ],
88
- "max_num_results" : os .getenv ("NUM_FILE_SEARCH_RESULTS" , 5 ),
89
- "filters" : {
90
- "type" : "or" ,
91
- "filters" : [
92
- {
93
- "type" : "and" ,
94
- "filters" : [
95
- {
96
- "type" : "eq" ,
97
- "key" : "city" ,
98
- "value" : current_session ["city" ],
99
- },
100
- {
101
- "type" : "eq" ,
102
- "key" : "state" ,
103
- "value" : current_session ["state" ],
104
- },
105
- ],
106
- }
107
- if current_session ["city" ] != "null"
108
- else None ,
109
- {
110
- "type" : "and" ,
111
- "filters" : [
112
- {
113
- "type" : "eq" ,
114
- "key" : "city" ,
115
- "value" : "null" ,
116
- },
117
- {
118
- "type" : "eq" ,
119
- "key" : "state" ,
120
- "value" : current_session ["state" ],
121
- },
122
- ],
123
- },
124
- ],
125
- },
126
- }
127
- ]
128
- if VECTOR_STORE_ID
129
- else None
130
- )
123
+ instructions = self .chat_manager .prepare_developer_instructions (current_session )
124
+ tools = self .chat_manager .prepare_openai_tools (current_session )
131
125
132
126
def generate ():
133
127
try :
134
128
# Use the new Responses API with streaming
135
129
response_stream = self .client .responses .create (
136
130
model = MODEL ,
137
- input = input_messages ,
131
+ input = current_session [ "messages" ] ,
138
132
instructions = instructions ,
139
133
reasoning = {"effort" : MODEL_REASONING_EFFORT },
140
134
stream = True ,
@@ -165,7 +159,7 @@ def generate():
165
159
yield f"Error: { str (e )} "
166
160
167
161
finally :
168
- self .tenant_session .set (session_id , current_session )
162
+ self .tenant_session .set (current_session )
169
163
170
164
return Response (
171
165
stream_with_context (generate ()),
0 commit comments