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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: olca
3
- Version: 0.2.60
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].createdAt.replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')
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
- from click import prompt
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.60
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
 
@@ -8,8 +8,10 @@ requests
8
8
  markdown
9
9
  langchain
10
10
  langchain-openai
11
+ langchain-ollama
11
12
  langchain-experimental
12
13
  click
13
14
  langgraph
14
15
  langfuse
15
16
  pytz
17
+ google.generativeai
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "olca"
10
- version = "0.2.60"
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.60",
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