sunholo 0.63.0__py3-none-any.whl → 0.64.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sunholo/agents/flask/qna_routes.py +148 -9
- sunholo/langfuse/callback.py +3 -4
- sunholo/utils/version.py +3 -0
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/METADATA +3 -2
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/RECORD +9 -8
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/WHEEL +0 -0
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/entry_points.txt +0 -0
- {sunholo-0.63.0.dist-info → sunholo-0.64.3.dist-info}/top_level.txt +0 -0
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import json
|
|
17
17
|
import traceback
|
|
18
18
|
import datetime
|
|
19
|
+
import uuid
|
|
19
20
|
|
|
20
21
|
from ...agents import extract_chat_history, handle_special_commands
|
|
21
22
|
from ...qna.parsers import parse_output
|
|
@@ -23,7 +24,11 @@ from ...streaming import start_streaming_chat
|
|
|
23
24
|
from ...archive import archive_qa
|
|
24
25
|
from ...logging import log
|
|
25
26
|
from ...utils.config import load_config
|
|
26
|
-
|
|
27
|
+
from ...utils.version import sunholo_version
|
|
28
|
+
import os
|
|
29
|
+
from ...gcs.add_file import add_file_to_gcs
|
|
30
|
+
|
|
31
|
+
|
|
27
32
|
try:
|
|
28
33
|
from flask import request, jsonify, Response
|
|
29
34
|
except ImportError:
|
|
@@ -34,6 +39,7 @@ try:
|
|
|
34
39
|
except ImportError:
|
|
35
40
|
pass
|
|
36
41
|
|
|
42
|
+
|
|
37
43
|
def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
38
44
|
|
|
39
45
|
@app.route("/")
|
|
@@ -155,9 +161,114 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
155
161
|
span.end(output=jsonify(bot_output))
|
|
156
162
|
trace.update(output=jsonify(bot_output))
|
|
157
163
|
|
|
164
|
+
# {'answer': 'output'}
|
|
158
165
|
return jsonify(bot_output)
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
@app.route('/openai/v1/chat/completions', methods=['POST'])
|
|
168
|
+
def openai_compatible_endpoint():
|
|
169
|
+
data = request.get_json()
|
|
170
|
+
model = data.pop('model', None)
|
|
171
|
+
messages = data.pop('messages', None)
|
|
172
|
+
chat_history = data.pop('chat_history', None)
|
|
173
|
+
stream = data.pop('stream', False)
|
|
174
|
+
|
|
175
|
+
if not messages:
|
|
176
|
+
return jsonify({"error": "No messages provided"}), 400
|
|
177
|
+
|
|
178
|
+
user_message = next((msg['content'] for msg in messages if msg['role'] == 'user'), None)
|
|
179
|
+
if not user_message:
|
|
180
|
+
return jsonify({"error": "No user message provided"}), 400
|
|
181
|
+
|
|
182
|
+
all_input = {
|
|
183
|
+
"user_input": user_message,
|
|
184
|
+
"chat_history": chat_history,
|
|
185
|
+
"kwargs": data
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
observed_stream_interpreter = observe()(stream_interpreter)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
response_id = str(uuid.uuid4())
|
|
192
|
+
|
|
193
|
+
def generate_response_content():
|
|
194
|
+
for chunk in start_streaming_chat(question=user_message,
|
|
195
|
+
vector_name=model,
|
|
196
|
+
qna_func=observed_stream_interpreter,
|
|
197
|
+
chat_history=all_input["chat_history"],
|
|
198
|
+
wait_time=all_input.get("stream_wait_time", 1),
|
|
199
|
+
timeout=all_input.get("stream_timeout", 60),
|
|
200
|
+
**all_input["kwargs"]
|
|
201
|
+
):
|
|
202
|
+
if isinstance(chunk, dict) and 'content' in chunk:
|
|
203
|
+
openai_chunk = {
|
|
204
|
+
"id": response_id,
|
|
205
|
+
"object": "chat.completion.chunk",
|
|
206
|
+
"created": int(datetime.time()),
|
|
207
|
+
"model": model,
|
|
208
|
+
"system_fingerprint": sunholo_version(),
|
|
209
|
+
"choices": [{
|
|
210
|
+
"index": 0,
|
|
211
|
+
"delta": {"content": chunk['content']},
|
|
212
|
+
"logprobs": None,
|
|
213
|
+
"finish_reason": None
|
|
214
|
+
}]
|
|
215
|
+
}
|
|
216
|
+
yield json.dumps(openai_chunk) + "\n"
|
|
217
|
+
|
|
218
|
+
final_chunk = {
|
|
219
|
+
"id": response_id,
|
|
220
|
+
"object": "chat.completion.chunk",
|
|
221
|
+
"created": int(datetime.time()),
|
|
222
|
+
"model": model,
|
|
223
|
+
"system_fingerprint": sunholo_version(),
|
|
224
|
+
"choices": [{
|
|
225
|
+
"index": 0,
|
|
226
|
+
"delta": {},
|
|
227
|
+
"logprobs": None,
|
|
228
|
+
"finish_reason": "stop"
|
|
229
|
+
}]
|
|
230
|
+
}
|
|
231
|
+
yield json.dumps(final_chunk) + "\n"
|
|
232
|
+
|
|
233
|
+
if stream:
|
|
234
|
+
return Response(generate_response_content(), content_type='text/plain; charset=utf-8')
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
bot_output = observed_stream_interpreter(
|
|
238
|
+
question=user_message,
|
|
239
|
+
vector_name=model,
|
|
240
|
+
chat_history=all_input["chat_history"],
|
|
241
|
+
**all_input["kwargs"]
|
|
242
|
+
)
|
|
243
|
+
bot_output = parse_output(bot_output)
|
|
244
|
+
|
|
245
|
+
openai_response = {
|
|
246
|
+
"id": response_id,
|
|
247
|
+
"object": "chat.completion",
|
|
248
|
+
"created": int(datetime.time()),
|
|
249
|
+
"model": model,
|
|
250
|
+
"system_fingerprint": sunholo_version(),
|
|
251
|
+
"choices": [{
|
|
252
|
+
"index": 0,
|
|
253
|
+
"message": {
|
|
254
|
+
"role": "assistant",
|
|
255
|
+
"content": bot_output.get('answer', ''),
|
|
256
|
+
},
|
|
257
|
+
"logprobs": None,
|
|
258
|
+
"finish_reason": "stop"
|
|
259
|
+
}],
|
|
260
|
+
"usage": {
|
|
261
|
+
"prompt_tokens": len(user_message.split()),
|
|
262
|
+
"completion_tokens": len(bot_output.get('answer', '').split()),
|
|
263
|
+
"total_tokens": len(user_message.split()) + len(bot_output.get('answer', '').split())
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return jsonify(openai_response)
|
|
268
|
+
|
|
269
|
+
except Exception as err:
|
|
270
|
+
return jsonify({'error': f'QNA_ERROR: An error occurred: {str(err)} traceback: {traceback.format_exc()}'}), 500
|
|
271
|
+
|
|
161
272
|
|
|
162
273
|
def create_langfuse_trace(request, vector_name):
|
|
163
274
|
try:
|
|
@@ -172,10 +283,8 @@ def create_langfuse_trace(request, vector_name):
|
|
|
172
283
|
session_id = request.headers.get("X-Session-ID")
|
|
173
284
|
message_source = request.headers.get("X-Message-Source")
|
|
174
285
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
package_version = version('sunholo')
|
|
178
|
-
tags = [f"sunholo-v{package_version}"]
|
|
286
|
+
package_version = sunholo_version()
|
|
287
|
+
tags = [package_version]
|
|
179
288
|
if message_source:
|
|
180
289
|
tags.append(message_source)
|
|
181
290
|
|
|
@@ -191,8 +300,28 @@ def prep_vac(request, vector_name):
|
|
|
191
300
|
#trace = create_langfuse_trace(request, vector_name)
|
|
192
301
|
trace = None
|
|
193
302
|
span = None
|
|
194
|
-
|
|
303
|
+
|
|
304
|
+
if request.content_type.startswith('application/json'):
|
|
305
|
+
data = request.get_json()
|
|
306
|
+
elif request.content_type.startswith('multipart/form-data'):
|
|
307
|
+
data = request.form.to_dict()
|
|
308
|
+
if 'file' in request.files:
|
|
309
|
+
file = request.files['file']
|
|
310
|
+
if file.filename != '':
|
|
311
|
+
log.info(f"Found file: {file.filename} to upload to GCS")
|
|
312
|
+
try:
|
|
313
|
+
image_uri, mime_type = handle_file_upload(file, vector_name)
|
|
314
|
+
data["image_uri"] = image_uri
|
|
315
|
+
data["mime"] = mime_type
|
|
316
|
+
except Exception as e:
|
|
317
|
+
return jsonify({'error': str(e), 'traceback': traceback.format_exc()}), 500
|
|
318
|
+
else:
|
|
319
|
+
return jsonify({"error": "No file selected"}), 400
|
|
320
|
+
else:
|
|
321
|
+
return jsonify({"error": "Unsupported content type"}), 400
|
|
322
|
+
|
|
195
323
|
log.info(f"vac/{vector_name} got data: {data}")
|
|
324
|
+
|
|
196
325
|
config, _ = load_config("config/llm_config.yaml")
|
|
197
326
|
vac_configs = config.get("vac")
|
|
198
327
|
if vac_configs:
|
|
@@ -213,7 +342,7 @@ def prep_vac(request, vector_name):
|
|
|
213
342
|
'vector_name': vector_name,
|
|
214
343
|
'chat_history': paired_messages,
|
|
215
344
|
'stream_wait_time': stream_wait_time,
|
|
216
|
-
'stream_timeout':stream_timeout,
|
|
345
|
+
'stream_timeout': stream_timeout,
|
|
217
346
|
'kwargs': data}
|
|
218
347
|
|
|
219
348
|
if trace:
|
|
@@ -233,4 +362,14 @@ def prep_vac(request, vector_name):
|
|
|
233
362
|
"command_response": command_response,
|
|
234
363
|
"all_input": all_input,
|
|
235
364
|
"vac_config": vac_config
|
|
236
|
-
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def handle_file_upload(file, vector_name):
|
|
369
|
+
try:
|
|
370
|
+
file.save(file.filename)
|
|
371
|
+
image_uri = add_file_to_gcs(file.filename, vector_name)
|
|
372
|
+
os.remove(file.filename) # Clean up the saved file
|
|
373
|
+
return image_uri, file.mimetype
|
|
374
|
+
except Exception as e:
|
|
375
|
+
raise Exception(f'File upload failed: {str(e)}')
|
sunholo/langfuse/callback.py
CHANGED
|
@@ -7,6 +7,8 @@ try:
|
|
|
7
7
|
except ImportError:
|
|
8
8
|
CallbackHandler = None
|
|
9
9
|
|
|
10
|
+
from ..utils.version import sunholo_version
|
|
11
|
+
|
|
10
12
|
def create_langfuse_callback(**kwargs):
|
|
11
13
|
|
|
12
14
|
if not CallbackHandler:
|
|
@@ -40,10 +42,7 @@ def add_langfuse_tracing(
|
|
|
40
42
|
session_id = request.headers.get("X-Session-ID")
|
|
41
43
|
message_source = request.headers.get("X-Message-Source")
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
from importlib.metadata import version
|
|
45
|
-
package_version = version('sunholo')
|
|
46
|
-
tags = [f"sunholo-v{package_version}"]
|
|
45
|
+
tags = [sunholo_version()]
|
|
47
46
|
if message_source:
|
|
48
47
|
tags.append(message_source)
|
|
49
48
|
|
sunholo/utils/version.py
ADDED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.64.3
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.64.3.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
21
|
Requires-Dist: google-auth
|
|
22
|
+
Requires-Dist: tenacity ==8.3.0
|
|
22
23
|
Requires-Dist: langchain
|
|
23
24
|
Requires-Dist: langchain-experimental
|
|
24
25
|
Requires-Dist: langchain-community
|
|
@@ -12,7 +12,7 @@ sunholo/agents/fastapi/base.py,sha256=clk76cHbUAvU0OYJrRfCWX_5f0ACbhDsIzYBhI3wyo
|
|
|
12
12
|
sunholo/agents/fastapi/qna_routes.py,sha256=DgK4Btu5XriOC1JaRQ4G_nWEjJfnQ0J5pyLanF6eF1g,3857
|
|
13
13
|
sunholo/agents/flask/__init__.py,sha256=uqfHNw2Ru3EJ4dJEcbp86h_lkquBQPMxZbjhV_xe3rs,72
|
|
14
14
|
sunholo/agents/flask/base.py,sha256=FgSaCODyoTtlstJtsqlLPScdgRUtv9_plxftdzHdVFo,809
|
|
15
|
-
sunholo/agents/flask/qna_routes.py,sha256=
|
|
15
|
+
sunholo/agents/flask/qna_routes.py,sha256=NAicUK_vfMK1ovR2wGLdplGnwV4w8_cfwFNOTjiMzNg,14074
|
|
16
16
|
sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
|
|
17
17
|
sunholo/archive/archive.py,sha256=C-UhG5x-XtZ8VheQp92IYJqgD0V3NFQjniqlit94t18,1197
|
|
18
18
|
sunholo/auth/__init__.py,sha256=4owDjSaWYkbTlPK47UHTOC0gCWbZsqn4ZIEw5NWZTlg,28
|
|
@@ -63,7 +63,7 @@ sunholo/gcs/add_file.py,sha256=QBzPnl5HVZ2Z-rWmBua7gJHBnLAizgXkObjC3dTbccs,4958
|
|
|
63
63
|
sunholo/gcs/download_url.py,sha256=8XSEf8byfubqs5CMQeF_tn9wxqwUTq3n9mo5mLNIUTA,4801
|
|
64
64
|
sunholo/gcs/metadata.py,sha256=C9sMPsHsq1ETetdQCqB3EBs3Kws8b8QHS9L7ei_v5aw,891
|
|
65
65
|
sunholo/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
|
-
sunholo/langfuse/callback.py,sha256=
|
|
66
|
+
sunholo/langfuse/callback.py,sha256=CTaos8sYcrga949BG6lIZ4I62DiiQSHxwz5re9XjDWQ,1677
|
|
67
67
|
sunholo/langfuse/prompts.py,sha256=HO4Zy9usn5tKooBPCKksuw4Lff3c03Ny5wqn4ce_xZM,1217
|
|
68
68
|
sunholo/llamaindex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
69
|
sunholo/llamaindex/generate.py,sha256=l1Picr-hVwkmAUD7XmTCa63qY9ERliFHQXwyX3BqB2Q,686
|
|
@@ -97,13 +97,14 @@ sunholo/utils/gcp_project.py,sha256=0ozs6tzI4qEvEeXb8MxLnCdEVoWKxlM6OH05htj7_tc,
|
|
|
97
97
|
sunholo/utils/parsers.py,sha256=OrHmASqIbI45atVOhiGodgLvnfrzkvVzyHnSvAXD89I,3841
|
|
98
98
|
sunholo/utils/timedelta.py,sha256=BbLabEx7_rbErj_YbNM0MBcaFN76DC4PTe4zD2ucezg,493
|
|
99
99
|
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
100
|
+
sunholo/utils/version.py,sha256=jjU_4anXBikJxPg0Wur0X-B7-ec1tC7jToykAnAG9Dg,108
|
|
100
101
|
sunholo/vertex/__init__.py,sha256=JvHcGFuv6R_nAhY2AdoqqhMpJ5ugeWPZ_svGhWrObBk,136
|
|
101
102
|
sunholo/vertex/init.py,sha256=JDMUaBRdednzbKF-5p33qqLit2LMsvgvWW-NRz0AqO0,1801
|
|
102
103
|
sunholo/vertex/memory_tools.py,sha256=8F1iTWnqEK9mX4W5RzCVKIjydIcNp6OFxjn_dtQ3GXo,5379
|
|
103
104
|
sunholo/vertex/safety.py,sha256=3meAX0HyGZYrH7rXPUAHxtI_3w_zoy_RX7Shtkoa660,1275
|
|
104
|
-
sunholo-0.
|
|
105
|
-
sunholo-0.
|
|
106
|
-
sunholo-0.
|
|
107
|
-
sunholo-0.
|
|
108
|
-
sunholo-0.
|
|
109
|
-
sunholo-0.
|
|
105
|
+
sunholo-0.64.3.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
106
|
+
sunholo-0.64.3.dist-info/METADATA,sha256=BmLFSkbWpUHnOLvrqJsgQZuotjYptCsYyPiLtR5bg9M,5971
|
|
107
|
+
sunholo-0.64.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
108
|
+
sunholo-0.64.3.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
109
|
+
sunholo-0.64.3.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
110
|
+
sunholo-0.64.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|