olca 0.2.34__py3-none-any.whl → 0.2.36__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- olca/fusewill_cli.py +22 -19
- olca/fusewill_utils.py +23 -5
- olca/olcacli.py +16 -17
- olca/tracing.py +38 -0
- {olca-0.2.34.dist-info → olca-0.2.36.dist-info}/METADATA +1 -1
- olca-0.2.36.dist-info/RECORD +11 -0
- olca-0.2.34.dist-info/RECORD +0 -10
- {olca-0.2.34.dist-info → olca-0.2.36.dist-info}/LICENSE +0 -0
- {olca-0.2.34.dist-info → olca-0.2.36.dist-info}/WHEEL +0 -0
- {olca-0.2.34.dist-info → olca-0.2.36.dist-info}/entry_points.txt +0 -0
- {olca-0.2.34.dist-info → olca-0.2.36.dist-info}/top_level.txt +0 -0
olca/fusewill_cli.py
CHANGED
@@ -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)
|
olca/fusewill_utils.py
CHANGED
@@ -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
|
olca/olcacli.py
CHANGED
@@ -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,21 +188,14 @@ def main():
|
|
186
188
|
|
187
189
|
config = load_config(olca_config_file)
|
188
190
|
|
189
|
-
#
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
import langsmith
|
198
|
-
LANGSMITH_API_KEY = os.getenv("LANGSMITH_API_KEY")
|
199
|
-
LANGCHAIN_API_KEY = os.getenv("LANGCHAIN_API_KEY")
|
200
|
-
if not LANGSMITH_API_KEY and not LANGCHAIN_API_KEY:
|
201
|
-
print("Error: LANGSMITH_API_KEY or LANGCHAIN_API_KEY environment variable is not set.")
|
202
|
-
exit(1)
|
203
|
-
client = langsmith.Client(api_key=LANGSMITH_API_KEY or LANGCHAIN_API_KEY)
|
191
|
+
# Initialize tracing
|
192
|
+
tracing_manager = TracingManager(config)
|
193
|
+
callbacks = tracing_manager.get_callbacks()
|
194
|
+
|
195
|
+
# Remove old tracing setup
|
196
|
+
tracing_enabled = config.get('tracing', False) or args.tracing
|
197
|
+
if tracing_enabled and not callbacks:
|
198
|
+
print("Warning: Tracing enabled but no handlers configured")
|
204
199
|
|
205
200
|
try:
|
206
201
|
|
@@ -286,7 +281,10 @@ def main():
|
|
286
281
|
|
287
282
|
|
288
283
|
try:
|
289
|
-
|
284
|
+
graph_config = {"callbacks": callbacks} if callbacks else {}
|
285
|
+
if recursion_limit:
|
286
|
+
graph_config["recursion_limit"] = recursion_limit
|
287
|
+
print_stream(graph.stream(inputs, config=graph_config))
|
290
288
|
except GraphRecursionError as e:
|
291
289
|
#print(f"Error: {e}")
|
292
290
|
print("Recursion limit reached. Please increase the 'recursion_limit' in the olca_config.yaml file.")
|
@@ -317,7 +315,8 @@ def initialize_config_file():
|
|
317
315
|
"recursion_limit": int(input("recursion_limit [12]: ") or default_recursion_limit),
|
318
316
|
"temperature": float(input("temperature [0]: ") or default_temperature),
|
319
317
|
"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
|
318
|
+
"tracing": input("tracing [true]: ").lower() in ["true", "yes", "y", "1", ""] or use_default_tracing,
|
319
|
+
"tracing_providers": ["langsmith", "langfuse"]
|
321
320
|
}
|
322
321
|
|
323
322
|
user_system_instructions = input(f"system_instructions [{default_system_instructions}]: ")
|
olca/tracing.py
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
import os
|
2
|
+
from langfuse.callback import CallbackHandler as LangfuseCallbackHandler
|
3
|
+
|
4
|
+
class TracingManager:
|
5
|
+
def __init__(self, config):
|
6
|
+
self.config = config
|
7
|
+
self.handlers = []
|
8
|
+
self.initialize_tracing()
|
9
|
+
|
10
|
+
def initialize_tracing(self):
|
11
|
+
tracing_enabled = self.config.get('tracing', False)
|
12
|
+
providers = self.config.get('tracing_providers', ['langsmith'])
|
13
|
+
|
14
|
+
if not tracing_enabled:
|
15
|
+
return
|
16
|
+
|
17
|
+
if 'langsmith' in providers:
|
18
|
+
self._setup_langsmith()
|
19
|
+
|
20
|
+
if 'langfuse' in providers:
|
21
|
+
handler = self._setup_langfuse()
|
22
|
+
if handler:
|
23
|
+
self.handlers.append(handler)
|
24
|
+
|
25
|
+
def _setup_langsmith(self):
|
26
|
+
api_key = os.getenv("LANGCHAIN_API_KEY") or os.getenv("LANGSMITH_API_KEY")
|
27
|
+
if api_key:
|
28
|
+
os.environ["LANGCHAIN_TRACING_V2"] = "true"
|
29
|
+
|
30
|
+
def _setup_langfuse(self):
|
31
|
+
if not (os.getenv("LANGFUSE_PUBLIC_KEY") and os.getenv("LANGFUSE_SECRET_KEY")):
|
32
|
+
print("Warning: LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEY not set for Langfuse tracing")
|
33
|
+
return None
|
34
|
+
|
35
|
+
return LangfuseCallbackHandler()
|
36
|
+
|
37
|
+
def get_callbacks(self):
|
38
|
+
return self.handlers if self.handlers else None
|
@@ -0,0 +1,11 @@
|
|
1
|
+
olca/__init__.py,sha256=3QyLLAys_KiiDIe-cfO_7QyY7di_qCaCS-sVziW2BOw,23
|
2
|
+
olca/fusewill_cli.py,sha256=Gf8CaYs7Uo4NH8QfgRNYalpmSUo047p9rzdkvIABHi8,7872
|
3
|
+
olca/fusewill_utils.py,sha256=IOIElqWCIsNzePlS1FZa5_35vySYLwbMUGW6UhNefIc,6065
|
4
|
+
olca/olcacli.py,sha256=MBWanmGn1vWiy0S2lhe_dJc7u-B14n3ywA7lEP4qttM,14578
|
5
|
+
olca/tracing.py,sha256=A6K9K_mhCPS1_NncFv2-7hbeMkqfKT3XgUCERusbIYE,1248
|
6
|
+
olca-0.2.36.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
7
|
+
olca-0.2.36.dist-info/METADATA,sha256=ovFeWWj5Xn2It7PqskYfvDNCSW0MjjO9bTKhb3y8DyY,25311
|
8
|
+
olca-0.2.36.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
9
|
+
olca-0.2.36.dist-info/entry_points.txt,sha256=AhP5FMv6vnOq9C76V_vxRVIO50smnZXG4RIY47oD2_U,103
|
10
|
+
olca-0.2.36.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
|
11
|
+
olca-0.2.36.dist-info/RECORD,,
|
olca-0.2.34.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
olca/__init__.py,sha256=3QyLLAys_KiiDIe-cfO_7QyY7di_qCaCS-sVziW2BOw,23
|
2
|
-
olca/fusewill_cli.py,sha256=-hq-uCQfx9Tkb8TTTJNgQS7hgigS9XDaNBL9CKAouMU,7415
|
3
|
-
olca/fusewill_utils.py,sha256=qh_ZGx9hV18wrdPM6ofXNFqyP51TeuoUeeTWfWIG1y8,5251
|
4
|
-
olca/olcacli.py,sha256=s-dqJRE6xqQLG_qSwp8prahRV3vZNueEaK7OXgmU9wc,14885
|
5
|
-
olca-0.2.34.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
6
|
-
olca-0.2.34.dist-info/METADATA,sha256=a453tzxvh71r4zn0ikUB-J9q-Btp2D3y3LRfDIGlCCU,25311
|
7
|
-
olca-0.2.34.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
8
|
-
olca-0.2.34.dist-info/entry_points.txt,sha256=AhP5FMv6vnOq9C76V_vxRVIO50smnZXG4RIY47oD2_U,103
|
9
|
-
olca-0.2.34.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
|
10
|
-
olca-0.2.34.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|