olca 0.2.33__tar.gz → 0.2.35__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.33
3
+ Version: 0.2.35
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
@@ -1,3 +1,4 @@
1
+ from ast import alias
1
2
  import os
2
3
  import sys
3
4
  sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
@@ -12,7 +13,8 @@ from fusewill_utils import (
12
13
  get_trace_by_id,
13
14
  open_trace_in_browser,
14
15
  print_traces,
15
- print_trace
16
+ print_trace,
17
+ list_traces_by_score # Ensure the updated function is imported
16
18
  )
17
19
  import dotenv
18
20
  import json
@@ -30,24 +32,24 @@ def get_single_char_input():
30
32
  return ch
31
33
 
32
34
  def main():
33
- parser = argparse.ArgumentParser(description="Langfuse CLI Wrapper")
35
+ parser = argparse.ArgumentParser(description="FuseWill Langfuse CLI Wrapper")
34
36
  subparsers = parser.add_subparsers(dest="command", help="Available commands")
35
37
 
36
38
  # list_traces command
37
39
  parser_list = subparsers.add_parser('list_traces', help='List traces',aliases=['lt'])
38
- parser_list.add_argument('--limit', type=int, default=100, help='Number of traces to fetch')
40
+ parser_list.add_argument('-L','--limit', type=int, default=100, help='Number of traces to fetch')
39
41
  parser_list.add_argument('--output_dir', type=str, default='../output/traces', help='Directory to save traces')
40
42
  parser_list.add_argument('-C','--comments', action='store_true', help='Show comments from the traces', default=False)
41
43
  parser_list.add_argument('-W','--browse-interact', action='store_true', help='Ask user to open each trace in browser')
42
44
 
43
45
  # create_dataset command
44
- parser_create_dataset = subparsers.add_parser('create_dataset', help='Create a new dataset')
46
+ parser_create_dataset = subparsers.add_parser('create_dataset', help='Create a new dataset',aliases=['cd'])
45
47
  parser_create_dataset.add_argument('name', help='Name of the dataset')
46
- parser_create_dataset.add_argument('--description', default='', help='Description of the dataset')
47
- parser_create_dataset.add_argument('--metadata', type=str, default='{}', help='Metadata in JSON format')
48
+ parser_create_dataset.add_argument('-D','--description', default='', help='Description of the dataset')
49
+ parser_create_dataset.add_argument('-M','--metadata', type=str, default='{}', help='Metadata in JSON format')
48
50
 
49
51
  # create_prompt command
50
- parser_create_prompt = subparsers.add_parser('create_prompt', help='Create a new prompt')
52
+ parser_create_prompt = subparsers.add_parser('create_prompt', help='Create a new prompt',aliases=['cp'])
51
53
  parser_create_prompt.add_argument('name', help='Name of the prompt')
52
54
  parser_create_prompt.add_argument('prompt_text', help='Prompt text')
53
55
  parser_create_prompt.add_argument('--model_name', default='gpt-4o-mini', help='Model name')
@@ -56,7 +58,7 @@ def main():
56
58
  parser_create_prompt.add_argument('--supported_languages', nargs='*', default=[], help='Supported languages')
57
59
 
58
60
  # update_prompt command
59
- parser_update_prompt = subparsers.add_parser('update_prompt', help='Update an existing prompt')
61
+ parser_update_prompt = subparsers.add_parser('update_prompt', help='Update an existing prompt',aliases=['up'])
60
62
  parser_update_prompt.add_argument('name', help='Name of the prompt')
61
63
  parser_update_prompt.add_argument('new_prompt_text', help='New prompt text')
62
64
 
@@ -65,11 +67,11 @@ def main():
65
67
  parser_delete_dataset.add_argument('name', help='Name of the dataset')
66
68
 
67
69
  # get_trace_by_id command
68
- parser_get_trace = subparsers.add_parser('get_trace_by_id', help='Get a trace by ID')
70
+ parser_get_trace = subparsers.add_parser('get_trace_by_id', help='Get a trace by ID',aliases=['gt'])
69
71
  parser_get_trace.add_argument('trace_id', help='Trace ID')
70
72
 
71
73
  # new_score command
72
- parser_new_score = subparsers.add_parser('new_score', help='Create a new score')
74
+ parser_new_score = subparsers.add_parser('new_score', help='Create a new score',aliases=['ns'])
73
75
  parser_new_score.add_argument('name', help='Score name')
74
76
  parser_new_score.add_argument('data_type', help='Data type of the score')
75
77
  parser_new_score.add_argument('--description', default='', help='Description of the score')
@@ -84,11 +86,11 @@ def main():
84
86
  parser_add_score.add_argument('--comment', default='', help='Comment for the score')
85
87
 
86
88
  # list_traces_by_score command
87
- parser_list_by_score = subparsers.add_parser('list_traces_by_score', help='List traces by score')
89
+ parser_list_by_score = subparsers.add_parser('list_traces_by_score', help='List traces by score', aliases=['ltbs','lbys','lts'])
88
90
  parser_list_by_score.add_argument('score_name', help='Score name')
89
91
  parser_list_by_score.add_argument('--min_value', type=float, help='Minimum score value')
90
92
  parser_list_by_score.add_argument('--max_value', type=float, help='Maximum score value')
91
- parser_list_by_score.add_argument('--limit', type=int, default=100, help='Number of traces to fetch')
93
+ parser_list_by_score.add_argument('-L','--limit', type=int, default=100, help='Number of traces to fetch')
92
94
 
93
95
  args = parser.parse_args()
94
96
 
@@ -115,7 +117,7 @@ def main():
115
117
  elif resp == 'q':
116
118
  print("Quitting.")
117
119
  break
118
- elif args.command == 'create_dataset':
120
+ elif args.command == 'create_dataset' or args.command == 'cd':
119
121
  metadata = json.loads(args.metadata)
120
122
  create_dataset(name=args.name, description=args.description, metadata=metadata)
121
123
  elif args.command == 'create_prompt':
@@ -127,16 +129,16 @@ def main():
127
129
  labels=args.labels,
128
130
  supported_languages=args.supported_languages
129
131
  )
130
- elif args.command == 'update_prompt':
132
+ elif args.command == 'update_prompt' or args.command == 'up':
131
133
  update_prompt(name=args.name, new_prompt_text=args.new_prompt_text)
132
134
  elif args.command == 'delete_dataset':
133
135
  delete_dataset(name=args.name)
134
- elif args.command == 'get_trace_by_id':
136
+ elif args.command == 'get_trace_by_id' or args.command == 'gt' :
135
137
  trace = get_trace_by_id(trace_id=args.trace_id)
136
138
  print(trace)
137
- elif args.command == 'new_score':
139
+ elif args.command == 'new_score' or args.command == 'ns':
138
140
  fu.create_score(name=args.name, data_type=args.data_type, description=args.description)
139
- elif args.command == 'add_score_to_trace':
141
+ elif args.command == 'add_score_to_trace' or args.command == 's2t':
140
142
  if not fu.score_exists(name=args.name):
141
143
  fu.create_score(name=args.name, data_type=args.data_type)
142
144
  fu.add_score_to_a_trace(
@@ -147,7 +149,7 @@ def main():
147
149
  data_type=args.data_type,
148
150
  comment=args.comment
149
151
  )
150
- elif args.command == 'list_traces_by_score':
152
+ elif args.command == 'list_traces_by_score' or args.command == 'ltbs' or args.command == 'lbys' or args.command == 'lts':
151
153
  traces = fu.list_traces_by_score(
152
154
  score_name=args.score_name,
153
155
  min_value=args.min_value,
@@ -155,7 +157,8 @@ def main():
155
157
  limit=args.limit
156
158
  )
157
159
  for trace in traces:
158
- print(f"Trace ID: {trace.id}, Name: {trace.name}")
160
+ print_trace(trace)
161
+ #print(f"Trace ID: {trace.id}, Name: {trace.name}")
159
162
  else:
160
163
  parser.print_help()
161
164
  exit(1)
@@ -3,6 +3,7 @@ import sys
3
3
  import json
4
4
  import dotenv
5
5
  import webbrowser
6
+ import requests # Add this import
6
7
 
7
8
  # Load .env from the current working directory
8
9
  dotenv.load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"))
@@ -53,15 +54,32 @@ def open_trace_in_browser(trace_id):
53
54
  print(f"Opening {full_url}")
54
55
  webbrowser.open(full_url)
55
56
 
57
+ def get_score_by_id(score_id):
58
+ """Retrieve score details by score ID."""
59
+ base_url = os.environ.get("LANGFUSE_HOST")
60
+ public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
61
+ secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
62
+ url = f"{base_url}/api/public/scores/{score_id}"
63
+ try:
64
+ response = requests.get(url, auth=(public_key, secret_key))
65
+ response.raise_for_status()
66
+ return response.json()
67
+ except Exception as e:
68
+ print(f"Error retrieving score {score_id}: {e}")
69
+ return None
70
+
56
71
  def print_trace(trace, show_comments=False):
57
72
  print(f"<Trace \n\tat=\"{trace.createdAt}\" \n\tid=\"{trace.id}\" \n\tname=\"{trace.name}\" \n\tsession_id=\"{trace.session_id}\" \n\tprojectId=\"{trace.projectId}\" >")
58
73
  print(f"<Input><CDATA[[\n{trace.input}\n]]></Input>")
59
74
  print(f"<Output><CDATA[[\n{trace.output}\n]]></Output>")
60
- print(f"<Metadata>{trace.metadata}</Metadata>")
75
+ if trace.metadata:
76
+ print(f"<Metadata>{trace.metadata}</Metadata>")
61
77
  if trace.scores:
62
78
  print("<Scores>")
63
- for score in trace.scores:
64
- print(f"{score}")
79
+ for score_id in trace.scores:
80
+ score = get_score_by_id(score_id)
81
+ if score:
82
+ print(f"<Score name=\"{score['name']}\" value=\"{score['value']}\" data_type=\"{score['dataType']}\" />")
65
83
  print("</Scores>")
66
84
  if show_comments and hasattr(trace, "comments"):
67
85
  print(f"<Comments>\n{trace.comments}\n</Comments>")
@@ -80,9 +98,10 @@ def list_traces_by_score(score_name, min_value=None, max_value=None, limit=100):
80
98
  traces = langfuse.get_traces(limit=limit)
81
99
  filtered_traces = []
82
100
  for trace in traces.data:
83
- for score in trace.scores:
84
- if score.name == score_name:
85
- if (min_value is None or score.value >= min_value) and (max_value is None or score.value <= max_value):
101
+ for score_id in trace.scores:
102
+ score = get_score_by_id(score_id)
103
+ if score and score.get('name') == score_name:
104
+ if (min_value is None or score.get('value') >= min_value) and (max_value is None or score.get('value') <= max_value):
86
105
  filtered_traces.append(trace)
87
106
  break
88
107
  return filtered_traces
@@ -166,6 +166,8 @@ def _parse_args():
166
166
  parser.add_argument("-y", "--yes", action="store_true", help="Accept the new file olca.yml")
167
167
  return parser.parse_args()
168
168
 
169
+ from olca.tracing import TracingManager
170
+
169
171
  def main():
170
172
  args = _parse_args()
171
173
  olca_config_file = 'olca.yml'
@@ -186,6 +188,10 @@ def main():
186
188
 
187
189
  config = load_config(olca_config_file)
188
190
 
191
+ # Initialize tracing
192
+ tracing_manager = TracingManager(config)
193
+ callbacks = tracing_manager.get_callbacks()
194
+
189
195
  # Check for tracing flag in config and CLI
190
196
  tracing_enabled = config.get('tracing', False) or args.tracing or os.getenv("LANGCHAIN_TRACING_V2") == "true"
191
197
  if tracing_enabled:
@@ -286,7 +292,7 @@ def main():
286
292
 
287
293
 
288
294
  try:
289
- print_stream(graph.stream(inputs, stream_mode="values"))
295
+ print_stream(graph.stream(inputs, config={"callbacks": callbacks} if callbacks else None))
290
296
  except GraphRecursionError as e:
291
297
  #print(f"Error: {e}")
292
298
  print("Recursion limit reached. Please increase the 'recursion_limit' in the olca_config.yaml file.")
@@ -317,7 +323,8 @@ def initialize_config_file():
317
323
  "recursion_limit": int(input("recursion_limit [12]: ") or default_recursion_limit),
318
324
  "temperature": float(input("temperature [0]: ") or default_temperature),
319
325
  "human": input("human [true]: ").lower() in ["true", "yes", "y", "1", ""] or use_default_human_input,
320
- "tracing": input("tracing [true]: ").lower() in ["true", "yes", "y", "1", ""] or use_default_tracing
326
+ "tracing": input("tracing [true]: ").lower() in ["true", "yes", "y", "1", ""] or use_default_tracing,
327
+ "tracing_providers": ["langsmith", "langfuse"]
321
328
  }
322
329
 
323
330
  user_system_instructions = input(f"system_instructions [{default_system_instructions}]: ")
@@ -0,0 +1,46 @@
1
+ import os
2
+ from langfuse.callback import CallbackHandler as LangfuseCallbackHandler
3
+ import langsmith
4
+
5
+ class TracingManager:
6
+ def __init__(self, config):
7
+ self.config = config
8
+ self.handlers = []
9
+ self.initialize_tracing()
10
+
11
+ def initialize_tracing(self):
12
+ tracing_enabled = self.config.get('tracing', False)
13
+ providers = self.config.get('tracing_providers', ['langsmith'])
14
+
15
+ if not tracing_enabled:
16
+ return
17
+
18
+ if 'langsmith' in providers:
19
+ handler = self._setup_langsmith()
20
+ if handler:
21
+ self.handlers.append(handler)
22
+
23
+ if 'langfuse' in providers:
24
+ handler = self._setup_langfuse()
25
+ if handler:
26
+ self.handlers.append(handler)
27
+
28
+ def _setup_langsmith(self):
29
+ os.environ["LANGCHAIN_TRACING_V2"] = "true"
30
+ api_key = os.getenv("LANGCHAIN_API_KEY") or os.getenv("LANGSMITH_API_KEY")
31
+
32
+ if not api_key:
33
+ print("Warning: LANGCHAIN_API_KEY/LANGSMITH_API_KEY not set for LangSmith tracing")
34
+ return None
35
+
36
+ return langsmith.Client(api_key=api_key)
37
+
38
+ def _setup_langfuse(self):
39
+ if not (os.getenv("LANGFUSE_PUBLIC_KEY") and os.getenv("LANGFUSE_SECRET_KEY")):
40
+ print("Warning: LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEY not set for Langfuse tracing")
41
+ return None
42
+
43
+ return LangfuseCallbackHandler()
44
+
45
+ def get_callbacks(self):
46
+ return self.handlers if self.handlers else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: olca
3
- Version: 0.2.33
3
+ Version: 0.2.35
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
@@ -6,6 +6,7 @@ olca/__init__.py
6
6
  olca/fusewill_cli.py
7
7
  olca/fusewill_utils.py
8
8
  olca/olcacli.py
9
+ olca/tracing.py
9
10
  olca.egg-info/PKG-INFO
10
11
  olca.egg-info/SOURCES.txt
11
12
  olca.egg-info/dependency_links.txt
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "olca"
10
- version = "0.2.33"
10
+ version = "0.2.35"
11
11
 
12
12
  description = "A Python package for experimental usage of Langchain and Human-in-the-Loop"
13
13
  readme = "README.md"
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='olca',
5
- version = "0.2.33",
5
+ version = "0.2.35",
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