olca 0.2.60__py3-none-any.whl → 0.2.61__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.
- olca/fusewill_cli.py +96 -0
- olca/fusewill_utils.py +79 -2
- olca/olcacli.py +32 -5
- {olca-0.2.60.dist-info → olca-0.2.61.dist-info}/METADATA +3 -1
- olca-0.2.61.dist-info/RECORD +14 -0
- olca-0.2.60.dist-info/RECORD +0 -14
- {olca-0.2.60.dist-info → olca-0.2.61.dist-info}/LICENSE +0 -0
- {olca-0.2.60.dist-info → olca-0.2.61.dist-info}/WHEEL +0 -0
- {olca-0.2.60.dist-info → olca-0.2.61.dist-info}/entry_points.txt +0 -0
- {olca-0.2.60.dist-info → olca-0.2.61.dist-info}/top_level.txt +0 -0
olca/fusewill_cli.py
CHANGED
@@ -120,6 +120,37 @@ def main():
|
|
120
120
|
parser_import.add_argument('--format', choices=['json','csv'], default='json', help='Import format')
|
121
121
|
parser_import.add_argument('--input', type=str, required=True, help='Input file path to read from')
|
122
122
|
|
123
|
+
# list_sessions command
|
124
|
+
parser_list_sessions = subparsers.add_parser('list_sessions', help='List sessions', aliases=['lss'])
|
125
|
+
parser_list_sessions.add_argument('-L','--limit', type=int, default=100, help='Number of sessions to fetch')
|
126
|
+
parser_list_sessions.add_argument('--start_date', type=str, help='Start date in ISO format (e.g., 2024-01-01)')
|
127
|
+
parser_list_sessions.add_argument('--end_date', type=str, help='End date in ISO format (e.g., 2024-12-31)')
|
128
|
+
parser_list_sessions.add_argument('--format', choices=['json','csv'], default='json', help='Output format (json or csv)')
|
129
|
+
parser_list_sessions.add_argument('-o','--output', type=str, help='Optional output file path')
|
130
|
+
|
131
|
+
# get_session command
|
132
|
+
parser_get_session = subparsers.add_parser('get_session', help='Get a session by ID', aliases=['gsess'])
|
133
|
+
parser_get_session.add_argument('session_id', help='Session ID')
|
134
|
+
parser_get_session.add_argument('-o','--output', type=str, help='Output file path (JSON or CSV)')
|
135
|
+
|
136
|
+
# get_media command
|
137
|
+
parser_get_media = subparsers.add_parser('get_media', help='Retrieve media details')
|
138
|
+
parser_get_media.add_argument('media_id', help='Media ID')
|
139
|
+
|
140
|
+
# get_upload_url command
|
141
|
+
parser_upload_url = subparsers.add_parser('get_upload_url', help='Get a presigned upload URL')
|
142
|
+
parser_upload_url.add_argument('trace_id', help='Trace ID')
|
143
|
+
parser_upload_url.add_argument('--content_type', required=True, help='Content-Type of the media')
|
144
|
+
parser_upload_url.add_argument('--content_length', type=int, required=True, help='Size of the media in bytes')
|
145
|
+
|
146
|
+
# get_daily_metrics command
|
147
|
+
parser_daily_metrics = subparsers.add_parser('get_daily_metrics', help='Fetch daily metrics', aliases=['gdm'])
|
148
|
+
parser_daily_metrics.add_argument('--trace_name', type=str, help='Optional trace name filter')
|
149
|
+
parser_daily_metrics.add_argument('--user_id', type=str, help='Optional user ID filter')
|
150
|
+
parser_daily_metrics.add_argument('--tags', nargs='*', help='Optional tags for filtering')
|
151
|
+
parser_daily_metrics.add_argument('--from_timestamp', type=str, help='Start date in ISO format')
|
152
|
+
parser_daily_metrics.add_argument('--to_timestamp', type=str, help='End date in ISO format')
|
153
|
+
|
123
154
|
args = parser.parse_args()
|
124
155
|
|
125
156
|
if args.command == 'list_traces' or args.command == 'lt':
|
@@ -241,6 +272,71 @@ def main():
|
|
241
272
|
fu.export_traces(format=args.format, output_path=output_path, start_date=args.start_date, end_date=args.end_date)
|
242
273
|
elif args.command == 'import_traces' or args.command == 'it':
|
243
274
|
fu.import_traces(format=args.format, input_path=args.input)
|
275
|
+
elif args.command == 'list_sessions' or args.command == 'lss':
|
276
|
+
sessions = fu.list_sessions(
|
277
|
+
limit=args.limit,
|
278
|
+
start_date=args.start_date,
|
279
|
+
end_date=args.end_date
|
280
|
+
)
|
281
|
+
|
282
|
+
if not sessions:
|
283
|
+
print("No sessions found.")
|
284
|
+
else:
|
285
|
+
if not args.output:
|
286
|
+
# Print to standard output
|
287
|
+
for s in sessions:
|
288
|
+
print(s)
|
289
|
+
else:
|
290
|
+
# Ensure output file extension matches --format
|
291
|
+
output_path = args.output
|
292
|
+
if not output_path.endswith(f".{args.format}"):
|
293
|
+
output_path += f".{args.format}"
|
294
|
+
|
295
|
+
if args.format == 'csv':
|
296
|
+
import csv
|
297
|
+
with open(output_path, 'w', newline='') as f:
|
298
|
+
writer = csv.DictWriter(f, fieldnames=sessions[0].keys())
|
299
|
+
writer.writeheader()
|
300
|
+
for s in sessions:
|
301
|
+
writer.writerow(s)
|
302
|
+
else: # default to JSON
|
303
|
+
import json
|
304
|
+
with open(output_path, 'w') as f:
|
305
|
+
json.dump(sessions, f, indent=2)
|
306
|
+
|
307
|
+
print(f"Sessions written to {os.path.realpath(output_path)}")
|
308
|
+
elif args.command == 'get_session' or args.command == 'gsess':
|
309
|
+
session = fu.get_session(args.session_id)
|
310
|
+
if session:
|
311
|
+
if args.output:
|
312
|
+
if args.output.endswith('.csv'):
|
313
|
+
import csv
|
314
|
+
with open(args.output, 'w', newline='') as f:
|
315
|
+
writer = csv.DictWriter(f, fieldnames=session.keys())
|
316
|
+
writer.writeheader()
|
317
|
+
writer.writerow(session)
|
318
|
+
print(f"Session written to {os.path.realpath(args.output)}")
|
319
|
+
else:
|
320
|
+
import json
|
321
|
+
with open(args.output, 'w') as f:
|
322
|
+
json.dump(session, f, indent=2)
|
323
|
+
print(f"Session written to {os.path.realpath(args.output)}")
|
324
|
+
else:
|
325
|
+
print(session)
|
326
|
+
else:
|
327
|
+
print(f"No session found for ID {args.session_id}")
|
328
|
+
elif args.command == 'get_media':
|
329
|
+
fu.get_media(args.media_id)
|
330
|
+
elif args.command == 'get_upload_url':
|
331
|
+
fu.get_upload_url(args.trace_id, args.content_type, args.content_length)
|
332
|
+
elif args.command == 'get_daily_metrics' or args.command == 'gdm':
|
333
|
+
fu.get_daily_metrics(
|
334
|
+
trace_name=args.trace_name,
|
335
|
+
user_id=args.user_id,
|
336
|
+
tags=args.tags,
|
337
|
+
from_timestamp=args.from_timestamp,
|
338
|
+
to_timestamp=args.to_timestamp
|
339
|
+
)
|
244
340
|
else:
|
245
341
|
parser.print_help()
|
246
342
|
exit(1)
|
olca/fusewill_utils.py
CHANGED
@@ -299,7 +299,7 @@ def export_traces(format='json', output_path=None, start_date=None, end_date=Non
|
|
299
299
|
# Sort traces by createdAt to ensure the oldest date is first
|
300
300
|
all_traces.sort(key=lambda x: x.createdAt)
|
301
301
|
first_trace_date = datetime.datetime.fromisoformat(all_traces[0].createdAt.replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')
|
302
|
-
last_trace_date = datetime.datetime.fromisoformat(all_traces[-1].
|
302
|
+
last_trace_date = datetime.datetime.fromisoformat(all_traces[-1].CreatedAt.replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')
|
303
303
|
print(f"Traces exported to {output_path}. Total traces exported: {len(all_traces)}")
|
304
304
|
print(f"Date range: {first_trace_date} to {last_trace_date}")
|
305
305
|
else:
|
@@ -337,4 +337,81 @@ def import_traces(format='json', input_path=None):
|
|
337
337
|
)
|
338
338
|
print(f"Imported {len(data)} traces from {input_path}")
|
339
339
|
except Exception as e:
|
340
|
-
print(f"Error importing traces: {e}")
|
340
|
+
print(f"Error importing traces: {e}")
|
341
|
+
|
342
|
+
def list_sessions(limit=100, start_date=None, end_date=None):
|
343
|
+
"""
|
344
|
+
List all sessions with optional date filtering.
|
345
|
+
Retrieves multiple pages so we don't miss older sessions.
|
346
|
+
"""
|
347
|
+
base_url = os.environ.get("LANGFUSE_HOST")
|
348
|
+
public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
|
349
|
+
secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
|
350
|
+
url = f"{base_url}/api/public/sessions"
|
351
|
+
sessions = []
|
352
|
+
page = 1
|
353
|
+
while True:
|
354
|
+
params = {
|
355
|
+
"page": page,
|
356
|
+
"limit": limit
|
357
|
+
}
|
358
|
+
if start_date:
|
359
|
+
params["fromTimestamp"] = datetime.datetime.fromisoformat(start_date).isoformat() + 'Z'
|
360
|
+
if end_date:
|
361
|
+
params["toTimestamp"] = datetime.datetime.fromisoformat(end_date).isoformat() + 'Z'
|
362
|
+
|
363
|
+
try:
|
364
|
+
response = requests.get(url, auth=(public_key, secret_key), params=params)
|
365
|
+
response.raise_for_status()
|
366
|
+
data = response.json()
|
367
|
+
except Exception as e:
|
368
|
+
print(f"Error retrieving sessions: {e}")
|
369
|
+
break
|
370
|
+
|
371
|
+
if "data" not in data or len(data["data"]) == 0:
|
372
|
+
break
|
373
|
+
|
374
|
+
sessions.extend(data["data"])
|
375
|
+
if len(data["data"]) < limit:
|
376
|
+
break
|
377
|
+
page += 1
|
378
|
+
|
379
|
+
return sessions
|
380
|
+
|
381
|
+
def get_session(session_id):
|
382
|
+
"""
|
383
|
+
Get details of a specific session including its traces.
|
384
|
+
"""
|
385
|
+
base_url = os.environ.get("LANGFUSE_HOST")
|
386
|
+
public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
|
387
|
+
secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
|
388
|
+
url = f"{base_url}/api/public/sessions/{session_id}"
|
389
|
+
|
390
|
+
try:
|
391
|
+
response = requests.get(url, auth=(public_key, secret_key))
|
392
|
+
response.raise_for_status()
|
393
|
+
return response.json()
|
394
|
+
except Exception as e:
|
395
|
+
print(f"Error retrieving session {session_id}: {e}")
|
396
|
+
return None
|
397
|
+
|
398
|
+
def get_upload_url(trace_id, content_type, content_length):
|
399
|
+
"""
|
400
|
+
Get a presigned URL for media upload.
|
401
|
+
"""
|
402
|
+
# TODO: Implement API call to POST /media
|
403
|
+
pass
|
404
|
+
|
405
|
+
def get_media(media_id):
|
406
|
+
"""
|
407
|
+
Retrieve media record details.
|
408
|
+
"""
|
409
|
+
# TODO: Implement API call to GET /media/{mediaId}
|
410
|
+
pass
|
411
|
+
|
412
|
+
def get_daily_metrics(trace_name=None, user_id=None, tags=None, from_timestamp=None, to_timestamp=None):
|
413
|
+
"""
|
414
|
+
Get daily metrics with optional filtering.
|
415
|
+
"""
|
416
|
+
# TODO: Implement API call to GET /metrics/daily with query params
|
417
|
+
pass
|
olca/olcacli.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#%%
|
2
2
|
import os
|
3
|
-
|
3
|
+
import sys
|
4
|
+
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
|
4
5
|
import dotenv
|
5
6
|
from langchain import hub
|
6
7
|
import argparse
|
@@ -153,6 +154,18 @@ def _parse_args():
|
|
153
154
|
parser.add_argument("-y", "--yes", action="store_true", help="Accept the new file olca.yml")
|
154
155
|
return parser.parse_args()
|
155
156
|
|
157
|
+
def parse_model_uri(uri: str):
|
158
|
+
# Example: "ollama://llama2@localhost"
|
159
|
+
if "://" not in uri:
|
160
|
+
return "openai", uri, None # default provider is openai
|
161
|
+
provider, rest = uri.split("://", 1)
|
162
|
+
host = None
|
163
|
+
if "@" in rest:
|
164
|
+
base_model, host = rest.split("@", 1)
|
165
|
+
else:
|
166
|
+
base_model = rest
|
167
|
+
return provider, base_model, host
|
168
|
+
|
156
169
|
def main():
|
157
170
|
args = _parse_args()
|
158
171
|
olca_config_file = 'olca.yml'
|
@@ -217,20 +230,33 @@ def main():
|
|
217
230
|
system_instructions = config.get('system_instructions', '')
|
218
231
|
user_input = config.get('user_input', '')
|
219
232
|
default_model_id = "gpt-4o-mini"
|
220
|
-
model_name = config.get('model_name', default_model_id)
|
221
233
|
recursion_limit = config.get('recursion_limit', 15)
|
222
234
|
disable_system_append = _parse_args().disable_system_append
|
223
|
-
|
224
235
|
# Use the system_instructions and user_input in your CLI logic
|
236
|
+
model_name = config.get('model_name', default_model_id)
|
237
|
+
provider, base_model, host = parse_model_uri(model_name)
|
238
|
+
|
239
|
+
if provider == "ollama":
|
240
|
+
from langchain_ollama import OllamaLLM
|
241
|
+
model = OllamaLLM(model=base_model, base_url=host if host else None)
|
242
|
+
elif provider == "openai":
|
243
|
+
from langchain_openai import ChatOpenAI
|
244
|
+
model = ChatOpenAI(model=base_model, temperature=0)
|
245
|
+
else:
|
246
|
+
# default fallback
|
247
|
+
from langchain_openai import ChatOpenAI
|
248
|
+
model = ChatOpenAI(model=model_name, temperature=0)
|
249
|
+
|
225
250
|
print("System Instructions:", system_instructions)
|
226
251
|
print("User Input:", user_input)
|
227
|
-
print("Model Name:", model_name)
|
228
252
|
print("Recursion Limit:", recursion_limit)
|
229
253
|
print("Trace:", tracing_enabled)
|
254
|
+
print("Model Name:", model_name)
|
230
255
|
|
231
|
-
model = ChatOpenAI(model=model_name, temperature=0)
|
232
256
|
selected_tools = ["terminal"]
|
233
257
|
|
258
|
+
disable_system_append = _parse_args().disable_system_append
|
259
|
+
|
234
260
|
human_switch = args.human
|
235
261
|
#look in olca_config.yaml for human: true
|
236
262
|
if "human" in config:
|
@@ -240,6 +266,7 @@ def main():
|
|
240
266
|
selected_tools.append("human")
|
241
267
|
|
242
268
|
if args.math:
|
269
|
+
from langchain_openai import OpenAI
|
243
270
|
math_llm = OpenAI()
|
244
271
|
selected_tools.append("llm-math")
|
245
272
|
if human_switch:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: olca
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.61
|
4
4
|
Summary: A Python package for experimental usage of Langchain and Human-in-the-Loop
|
5
5
|
Home-page: https://github.com/jgwill/olca
|
6
6
|
Author: Jean GUillaume ISabelle
|
@@ -361,11 +361,13 @@ Requires-Dist: requests
|
|
361
361
|
Requires-Dist: markdown
|
362
362
|
Requires-Dist: langchain
|
363
363
|
Requires-Dist: langchain-openai
|
364
|
+
Requires-Dist: langchain-ollama
|
364
365
|
Requires-Dist: langchain-experimental
|
365
366
|
Requires-Dist: click
|
366
367
|
Requires-Dist: langgraph
|
367
368
|
Requires-Dist: langfuse
|
368
369
|
Requires-Dist: pytz
|
370
|
+
Requires-Dist: google.generativeai
|
369
371
|
|
370
372
|
# oLCa
|
371
373
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
olca/__init__.py,sha256=3QyLLAys_KiiDIe-cfO_7QyY7di_qCaCS-sVziW2BOw,23
|
2
|
+
olca/fusewill_cli.py,sha256=7etgdpM64-jXGLlALG7PtwICAzoLKYGMBRvHf5nMLic,17119
|
3
|
+
olca/fusewill_utils.py,sha256=LEKEDboyCm14_yvypE6lTed9j_uJN4K8vVdvYi6JoJs,14903
|
4
|
+
olca/olcacli.py,sha256=w9yo2BSX9b2t6_rljAmYJTbyLCQ6LRfXqLxi8sWb6FQ,11181
|
5
|
+
olca/olcahelper.py,sha256=WdN6-K-N7-HnB9L_px6TsDKWiTXIusZM2I1d0GNQnFs,3322
|
6
|
+
olca/prompts.py,sha256=q7lvDZ8n_K6ea2nu3K5R2fgBgQYrCIEjh0cA9fUlMFI,3697
|
7
|
+
olca/tracing.py,sha256=GSuXIKmIMQ9V2gLkKcin142Z2QpyS6obsnj8Tf-1zHc,1621
|
8
|
+
olca/utils.py,sha256=zM94HDMDYF95Yd9ubeOK6vuepbQN4kDFh0rTvaVFagI,912
|
9
|
+
olca-0.2.61.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
10
|
+
olca-0.2.61.dist-info/METADATA,sha256=ABqdy467xpsMFu7jwU1Ac74htUamHpWleksX4nwsWFY,25398
|
11
|
+
olca-0.2.61.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
12
|
+
olca-0.2.61.dist-info/entry_points.txt,sha256=AhP5FMv6vnOq9C76V_vxRVIO50smnZXG4RIY47oD2_U,103
|
13
|
+
olca-0.2.61.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
|
14
|
+
olca-0.2.61.dist-info/RECORD,,
|
olca-0.2.60.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
olca/__init__.py,sha256=3QyLLAys_KiiDIe-cfO_7QyY7di_qCaCS-sVziW2BOw,23
|
2
|
-
olca/fusewill_cli.py,sha256=muFBmWm1HPWrcpEGLEH4YMInEw9fIrWxb1aO5yr07n8,12156
|
3
|
-
olca/fusewill_utils.py,sha256=BnNovYOzfNodhO-CoJYTX2uNonFeV1e88YwZYO1B-UM,12487
|
4
|
-
olca/olcacli.py,sha256=NGYxZw_kYI9y9DmXu5dk02S_UOqVw05FWlzQ2gjXv00,10214
|
5
|
-
olca/olcahelper.py,sha256=WdN6-K-N7-HnB9L_px6TsDKWiTXIusZM2I1d0GNQnFs,3322
|
6
|
-
olca/prompts.py,sha256=q7lvDZ8n_K6ea2nu3K5R2fgBgQYrCIEjh0cA9fUlMFI,3697
|
7
|
-
olca/tracing.py,sha256=GSuXIKmIMQ9V2gLkKcin142Z2QpyS6obsnj8Tf-1zHc,1621
|
8
|
-
olca/utils.py,sha256=zM94HDMDYF95Yd9ubeOK6vuepbQN4kDFh0rTvaVFagI,912
|
9
|
-
olca-0.2.60.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
10
|
-
olca-0.2.60.dist-info/METADATA,sha256=lBFrltW-p-YUMASGo12IOTjPJ1XLD2ulRRG_NNx2vH0,25331
|
11
|
-
olca-0.2.60.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
12
|
-
olca-0.2.60.dist-info/entry_points.txt,sha256=AhP5FMv6vnOq9C76V_vxRVIO50smnZXG4RIY47oD2_U,103
|
13
|
-
olca-0.2.60.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
|
14
|
-
olca-0.2.60.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|