olca 0.2.60__tar.gz → 0.2.61__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {olca-0.2.60 → olca-0.2.61}/PKG-INFO +3 -1
- {olca-0.2.60 → olca-0.2.61}/olca/fusewill_cli.py +96 -0
- {olca-0.2.60 → olca-0.2.61}/olca/fusewill_utils.py +79 -2
- {olca-0.2.60 → olca-0.2.61}/olca/olcacli.py +32 -5
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/PKG-INFO +3 -1
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/requires.txt +2 -0
- {olca-0.2.60 → olca-0.2.61}/pyproject.toml +3 -1
- {olca-0.2.60 → olca-0.2.61}/setup.py +1 -1
- {olca-0.2.60 → olca-0.2.61}/LICENSE +0 -0
- {olca-0.2.60 → olca-0.2.61}/README.md +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca/__init__.py +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca/olcahelper.py +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca/prompts.py +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca/tracing.py +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca/utils.py +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/SOURCES.txt +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/dependency_links.txt +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/entry_points.txt +0 -0
- {olca-0.2.60 → olca-0.2.61}/olca.egg-info/top_level.txt +0 -0
- {olca-0.2.60 → olca-0.2.61}/setup.cfg +0 -0
@@ -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
|
|
@@ -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)
|
@@ -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
|
@@ -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
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
7
7
|
|
8
8
|
[project]
|
9
9
|
name = "olca"
|
10
|
-
version = "0.2.
|
10
|
+
version = "0.2.61"
|
11
11
|
|
12
12
|
description = "A Python package for experimental usage of Langchain and Human-in-the-Loop"
|
13
13
|
readme = "README.md"
|
@@ -27,11 +27,13 @@ dependencies = [
|
|
27
27
|
"markdown",
|
28
28
|
"langchain",
|
29
29
|
"langchain-openai",
|
30
|
+
"langchain-ollama",
|
30
31
|
"langchain-experimental",
|
31
32
|
"click",
|
32
33
|
"langgraph",
|
33
34
|
"langfuse",
|
34
35
|
"pytz",
|
36
|
+
"google.generativeai",
|
35
37
|
]
|
36
38
|
classifiers = [
|
37
39
|
"Programming Language :: Python :: 3",
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='olca',
|
5
|
-
version = "0.2.
|
5
|
+
version = "0.2.61",
|
6
6
|
author='Jean GUillaume ISabelle',
|
7
7
|
author_email='jgi@jgwill.com',
|
8
8
|
description='A Python package for experimenting with Langchain agent and interactivity in Terminal modalities.',
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|