olca 0.2.34__tar.gz → 0.2.35__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {olca-0.2.34 → olca-0.2.35}/PKG-INFO +1 -1
- {olca-0.2.34 → olca-0.2.35}/olca/fusewill_cli.py +22 -19
- {olca-0.2.34 → olca-0.2.35}/olca/fusewill_utils.py +23 -5
- {olca-0.2.34 → olca-0.2.35}/olca/olcacli.py +9 -2
- olca-0.2.35/olca/tracing.py +46 -0
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/PKG-INFO +1 -1
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/SOURCES.txt +1 -0
- {olca-0.2.34 → olca-0.2.35}/pyproject.toml +1 -1
- {olca-0.2.34 → olca-0.2.35}/setup.py +1 -1
- {olca-0.2.34 → olca-0.2.35}/LICENSE +0 -0
- {olca-0.2.34 → olca-0.2.35}/README.md +0 -0
- {olca-0.2.34 → olca-0.2.35}/olca/__init__.py +0 -0
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/dependency_links.txt +0 -0
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/entry_points.txt +0 -0
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/requires.txt +0 -0
- {olca-0.2.34 → olca-0.2.35}/olca.egg-info/top_level.txt +0 -0
- {olca-0.2.34 → olca-0.2.35}/setup.cfg +0 -0
@@ -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
|
-
|
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,6 +54,20 @@ 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>")
|
@@ -61,8 +76,10 @@ def print_trace(trace, show_comments=False):
|
|
61
76
|
print(f"<Metadata>{trace.metadata}</Metadata>")
|
62
77
|
if trace.scores:
|
63
78
|
print("<Scores>")
|
64
|
-
for
|
65
|
-
|
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']}\" />")
|
66
83
|
print("</Scores>")
|
67
84
|
if show_comments and hasattr(trace, "comments"):
|
68
85
|
print(f"<Comments>\n{trace.comments}\n</Comments>")
|
@@ -81,9 +98,10 @@ def list_traces_by_score(score_name, min_value=None, max_value=None, limit=100):
|
|
81
98
|
traces = langfuse.get_traces(limit=limit)
|
82
99
|
filtered_traces = []
|
83
100
|
for trace in traces.data:
|
84
|
-
for
|
85
|
-
|
86
|
-
|
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):
|
87
105
|
filtered_traces.append(trace)
|
88
106
|
break
|
89
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,
|
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
|
@@ -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.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
|
File without changes
|
File without changes
|