olca 0.2.55__tar.gz → 0.2.57__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {olca-0.2.55 → olca-0.2.57}/PKG-INFO +1 -1
- {olca-0.2.55 → olca-0.2.57}/olca/fusewill_cli.py +60 -0
- {olca-0.2.55 → olca-0.2.57}/olca/fusewill_utils.py +76 -3
- {olca-0.2.55 → olca-0.2.57}/olca/olcacli.py +2 -51
- olca-0.2.57/olca/prompts.py +38 -0
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/PKG-INFO +1 -1
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/SOURCES.txt +1 -0
- {olca-0.2.55 → olca-0.2.57}/pyproject.toml +1 -1
- {olca-0.2.55 → olca-0.2.57}/setup.py +1 -1
- {olca-0.2.55 → olca-0.2.57}/LICENSE +0 -0
- {olca-0.2.55 → olca-0.2.57}/README.md +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca/__init__.py +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca/olcahelper.py +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca/tracing.py +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca/utils.py +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/dependency_links.txt +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/entry_points.txt +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/requires.txt +0 -0
- {olca-0.2.55 → olca-0.2.57}/olca.egg-info/top_level.txt +0 -0
- {olca-0.2.55 → olca-0.2.57}/setup.cfg +0 -0
@@ -92,6 +92,20 @@ def main():
|
|
92
92
|
parser_list_by_score.add_argument('--max_value', type=float, help='Maximum score value')
|
93
93
|
parser_list_by_score.add_argument('-L','--limit', type=int, default=100, help='Number of traces to fetch')
|
94
94
|
|
95
|
+
# list_scores command
|
96
|
+
parser_list_scores = subparsers.add_parser('list_scores', help='List all scores', aliases=['ls'])
|
97
|
+
parser_list_scores.add_argument('-o', '--output', type=str, help='Output JSON file path')
|
98
|
+
|
99
|
+
# search_traces command
|
100
|
+
parser_search = subparsers.add_parser('search_traces', help='Search and filter traces with advanced options', aliases=['st'])
|
101
|
+
parser_search.add_argument('--start_date', type=str, help='Start date in ISO format (e.g., 2024-01-01)')
|
102
|
+
parser_search.add_argument('--end_date', type=str, help='End date in ISO format (e.g., 2024-12-31)')
|
103
|
+
parser_search.add_argument('--keywords', nargs='*', help='Keywords to search in input or output')
|
104
|
+
parser_search.add_argument('--tags', nargs='*', help='Tags to filter traces')
|
105
|
+
parser_search.add_argument('--metadata', nargs='*', help='Metadata filters in key=value format')
|
106
|
+
parser_search.add_argument('-L', '--limit', type=int, default=100, help='Number of traces to fetch')
|
107
|
+
parser_search.add_argument('-o', '--output', type=str, help='Output JSON file path')
|
108
|
+
|
95
109
|
args = parser.parse_args()
|
96
110
|
|
97
111
|
if args.command == 'list_traces' or args.command == 'lt':
|
@@ -159,6 +173,52 @@ def main():
|
|
159
173
|
for trace in traces:
|
160
174
|
print_trace(trace)
|
161
175
|
#print(f"Trace ID: {trace.id}, Name: {trace.name}")
|
176
|
+
elif args.command == 'list_scores' or args.command == 'ls':
|
177
|
+
scores = fu.list_scores()
|
178
|
+
if scores:
|
179
|
+
if args.output:
|
180
|
+
try:
|
181
|
+
with open(args.output, 'w') as f:
|
182
|
+
json.dump(scores, f, indent=2)
|
183
|
+
print(f"Scores written to {os.path.realpath(args.output)}")
|
184
|
+
except Exception as e:
|
185
|
+
print(f"Error writing to file {args.output}: {e}")
|
186
|
+
else:
|
187
|
+
print(json.dumps(scores, indent=2))
|
188
|
+
else:
|
189
|
+
print("No scores found.")
|
190
|
+
elif args.command == 'search_traces' or args.command == 'st':
|
191
|
+
metadata_filters = {}
|
192
|
+
if args.metadata:
|
193
|
+
for item in args.metadata:
|
194
|
+
if '=' in item:
|
195
|
+
key, value = item.split('=', 1)
|
196
|
+
metadata_filters[key] = value
|
197
|
+
else:
|
198
|
+
print(f"Ignoring invalid metadata filter: {item}")
|
199
|
+
|
200
|
+
traces = fu.search_traces(
|
201
|
+
start_date=args.start_date,
|
202
|
+
end_date=args.end_date,
|
203
|
+
keywords=args.keywords,
|
204
|
+
tags=args.tags,
|
205
|
+
metadata_filters=metadata_filters,
|
206
|
+
limit=args.limit
|
207
|
+
)
|
208
|
+
|
209
|
+
if traces:
|
210
|
+
if args.output:
|
211
|
+
try:
|
212
|
+
with open(args.output, 'w') as f:
|
213
|
+
json.dump([trace.__dict__ for trace in traces], f, indent=2)
|
214
|
+
print(f"Traces written to {os.path.realpath(args.output)}")
|
215
|
+
except Exception as e:
|
216
|
+
print(f"Error writing to file {args.output}: {e}")
|
217
|
+
else:
|
218
|
+
for trace in traces:
|
219
|
+
fu.print_trace(trace)
|
220
|
+
else:
|
221
|
+
print("No traces found matching the criteria.")
|
162
222
|
else:
|
163
223
|
parser.print_help()
|
164
224
|
exit(1)
|
@@ -4,6 +4,8 @@ import json
|
|
4
4
|
import dotenv
|
5
5
|
import webbrowser
|
6
6
|
import requests # Add this import
|
7
|
+
import datetime # Add this import
|
8
|
+
import pytz # Add this import
|
7
9
|
|
8
10
|
# Load .env from the current working directory
|
9
11
|
dotenv.load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"))
|
@@ -43,7 +45,7 @@ langfuse = Langfuse(
|
|
43
45
|
secret_key=os.environ.get("LANGFUSE_SECRET_KEY"),
|
44
46
|
host=os.environ.get("LANGFUSE_HOST")
|
45
47
|
)
|
46
|
-
|
48
|
+
|
47
49
|
def open_trace_in_browser(trace_id):
|
48
50
|
base_url = os.environ.get("LANGFUSE_HOST")
|
49
51
|
project_id = os.environ.get("LANGFUSE_PROJECT_ID")
|
@@ -68,6 +70,20 @@ def get_score_by_id(score_id):
|
|
68
70
|
print(f"Error retrieving score {score_id}: {e}")
|
69
71
|
return None
|
70
72
|
|
73
|
+
def list_scores():
|
74
|
+
"""Retrieve all score configurations."""
|
75
|
+
base_url = os.environ.get("LANGFUSE_HOST")
|
76
|
+
public_key = os.environ.get("LANGFUSE_PUBLIC_KEY")
|
77
|
+
secret_key = os.environ.get("LANGFUSE_SECRET_KEY")
|
78
|
+
url = f"{base_url}/api/public/score-configs"
|
79
|
+
try:
|
80
|
+
response = requests.get(url, auth=(public_key, secret_key))
|
81
|
+
response.raise_for_status()
|
82
|
+
return response.json()
|
83
|
+
except Exception as e:
|
84
|
+
print(f"Error retrieving scores: {e}")
|
85
|
+
return None
|
86
|
+
|
71
87
|
def print_trace(trace, show_comments=False):
|
72
88
|
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}\" >")
|
73
89
|
print(f"<Input><CDATA[[\n{trace.input}\n]]></Input>")
|
@@ -157,7 +173,7 @@ def create_prompt(name, prompt_text, model_name, temperature, labels=None, suppo
|
|
157
173
|
}
|
158
174
|
)
|
159
175
|
def get_prompt(name, label="production"):
|
160
|
-
return langfuse.get_prompt(name=name,label=
|
176
|
+
return langfuse.get_prompt(name=name,label=label)
|
161
177
|
|
162
178
|
def update_prompt(name, new_prompt_text):
|
163
179
|
prompt = langfuse.get_prompt(name=name)
|
@@ -168,4 +184,61 @@ def delete_dataset(name):
|
|
168
184
|
dataset.delete()
|
169
185
|
|
170
186
|
def get_trace_by_id(trace_id):
|
171
|
-
return langfuse.get_trace(trace_id)
|
187
|
+
return langfuse.get_trace(trace_id)
|
188
|
+
|
189
|
+
def search_traces(
|
190
|
+
start_date=None,
|
191
|
+
end_date=None,
|
192
|
+
keywords=None,
|
193
|
+
tags=None,
|
194
|
+
metadata_filters=None,
|
195
|
+
limit=100
|
196
|
+
):
|
197
|
+
"""
|
198
|
+
Search and filter traces based on date range, keywords, tags, and metadata.
|
199
|
+
|
200
|
+
Parameters:
|
201
|
+
start_date (str): ISO format date string for the start of the date range.
|
202
|
+
end_date (str): ISO format date string for the end of the date range.
|
203
|
+
keywords (list): List of keywords to search in input or output.
|
204
|
+
tags (list): List of tags to filter traces.
|
205
|
+
metadata_filters (dict): Dictionary of metadata key-value pairs for filtering.
|
206
|
+
limit (int): Number of traces to fetch.
|
207
|
+
|
208
|
+
Returns:
|
209
|
+
list: Filtered list of traces.
|
210
|
+
"""
|
211
|
+
try:
|
212
|
+
params = {}
|
213
|
+
if start_date:
|
214
|
+
from_timestamp = datetime.datetime.fromisoformat(start_date)
|
215
|
+
from_timestamp = from_timestamp.replace(tzinfo=pytz.UTC)
|
216
|
+
params['from_timestamp'] = from_timestamp
|
217
|
+
if end_date:
|
218
|
+
to_timestamp = datetime.datetime.fromisoformat(end_date)
|
219
|
+
to_timestamp = to_timestamp.replace(tzinfo=pytz.UTC)
|
220
|
+
params['to_timestamp'] = to_timestamp
|
221
|
+
if tags:
|
222
|
+
params['tags'] = tags
|
223
|
+
if metadata_filters:
|
224
|
+
for key, value in metadata_filters.items():
|
225
|
+
params[f'metadata.{key}'] = value
|
226
|
+
|
227
|
+
traces = langfuse.get_traces(limit=limit, **params)
|
228
|
+
if not traces:
|
229
|
+
return []
|
230
|
+
|
231
|
+
filtered_traces = traces.data
|
232
|
+
|
233
|
+
if keywords:
|
234
|
+
keyword_set = set(keyword.lower() for keyword in keywords)
|
235
|
+
filtered_traces = [
|
236
|
+
trace for trace in filtered_traces
|
237
|
+
if any(keyword in trace.input.lower() for keyword in keyword_set) or
|
238
|
+
any(keyword in trace.output.lower() for keyword in keyword_set)
|
239
|
+
]
|
240
|
+
|
241
|
+
return filtered_traces
|
242
|
+
except Exception as e:
|
243
|
+
print(f"Error searching traces: {e}")
|
244
|
+
return []
|
@@ -8,49 +8,12 @@ import yaml
|
|
8
8
|
from olca.utils import load_environment, initialize_langfuse
|
9
9
|
from olca.tracing import TracingManager
|
10
10
|
from olca.olcahelper import setup_required_directories, initialize_config_file
|
11
|
-
import
|
12
|
-
import httpx
|
13
|
-
from openai.error import APIConnectionError
|
11
|
+
from prompts import SYSTEM_PROMPT_APPEND, HUMAN_APPEND_PROMPT
|
14
12
|
|
15
13
|
#jgwill/olca1
|
16
14
|
#olca1_prompt = hub.pull("jgwill/olca1") #Future use
|
17
15
|
#https://smith.langchain.com/hub/jgwill/olca1
|
18
|
-
SYSTEM_PROMPT_APPEND="""
|
19
|
-
You do what is above and consider the following when doing the task:
|
20
|
-
---
|
21
|
-
* Write or append instructions to ./.olca/instructions.txt on how to perform tasks (in terms of reflection and action steps. example: cli syntax to execute something). You read that file to learn how to do your job if it exists (example: when you starts, you read this to know more on what you learned to do in previous iterations (as it might not be the first time you ran, this file will intruct you where we are. You can also deduce this from the user message)). You update it with what you learned and keep it up to date. You dont erase the content of the file but if what you find in it is not related to your task or is semantically the same, you clean the whole think so its clear. Dont output all these details you do this internally, no output to the stardard output. You read it back from time to time to remember what you did, learned and how to make it and what the user wants.
|
22
|
-
* Produce a report in ./reports/report-olca-[TIMESTAMP].md
|
23
|
-
* Report to the user if repeated errors are encountered if human tool is accessible (you interact, stating the errors and asking for instructions from the user (you never quit without the user explicitly stating to end the flow)).
|
24
|
-
* Output the iteration number and plan to the standard output during each loop.
|
25
|
-
* If you are given an issue_id, you commit the work to that issue and push your results (dont output the git push to the standard output).
|
26
|
-
* Do not comment on your final results; just output them but keep logging your action steps you do internally (all reflection and action steps).
|
27
|
-
* Dont modify the file: olca.yml
|
28
|
-
* If github issue related, dont checkout a branch except if asked otherwise.
|
29
|
-
* You dont checkout branches, I repeat, you dont checkout branches.
|
30
|
-
* Generate your TIMESTAMP with the following command: date +'%Y%m%d%H%M%S' only once at the beginning of your script.
|
31
|
-
* Make sure if you Switched to branch, you switch back to main before the end of your script.
|
32
|
-
* Try to observe that you keep doing the same thing over and over again and stop right away if you see that (dont do that if you are developping a story)
|
33
|
-
* Be quiet with trivial output in the terminal.
|
34
|
-
* Write and update your plan in ./.olca/plan.md
|
35
|
-
* You watch out for basic syntax errors with your args when executing echo commands. (example: Syntax error: Unterminated quoted string, make sure to escape your single and double quotes)
|
36
|
-
----
|
37
|
-
REMEMBER: Dont introduce nor conclude, just output results. No comments. you present in a coherent format without preambles or fluff. Never use the word "determination" and we never brainstorm (we conceptualize the result we want in the germination phase then transform it into vision by choice and work as assimilating the vision to until the last phase which is completing our work).
|
38
|
-
"""
|
39
16
|
|
40
|
-
HUMAN_APPEND_PROMPT = """
|
41
|
-
* Utilize the 'human' tool for interactions as directed.
|
42
|
-
* Communicate clearly and simply, avoiding exaggeration.
|
43
|
-
Example Interaction:
|
44
|
-
<example>
|
45
|
-
'==============================================
|
46
|
-
{ PURPOSE_OF_THE_MESSAGE_SHORT }
|
47
|
-
==============================================
|
48
|
-
{ CURRENT_STATUS_OR_MESSAGE_CONTENT }
|
49
|
-
==============================================
|
50
|
-
{ PROMPT_FOR_USER_INPUT_SHORT } :
|
51
|
-
</example>
|
52
|
-
REMEMBER: Never ask to brainstorm (NEVER USE THAT WORD)
|
53
|
-
"""
|
54
17
|
def get_input() -> str:
|
55
18
|
print("----------------------")
|
56
19
|
contents = []
|
@@ -308,19 +271,7 @@ def main():
|
|
308
271
|
graph_config = {"callbacks": callbacks} if callbacks else {}
|
309
272
|
if recursion_limit:
|
310
273
|
graph_config["recursion_limit"] = recursion_limit
|
311
|
-
|
312
|
-
retry_attempts = 3
|
313
|
-
for attempt in range(retry_attempts):
|
314
|
-
try:
|
315
|
-
print_stream(graph.stream(inputs, config=graph_config))
|
316
|
-
break
|
317
|
-
except (httpx.ConnectError, APIConnectionError) as e:
|
318
|
-
if attempt < retry_attempts - 1:
|
319
|
-
print(f"Network error encountered: {e}. Retrying in 5 seconds...")
|
320
|
-
time.sleep(5)
|
321
|
-
else:
|
322
|
-
print("Failed to connect after multiple attempts. Exiting.")
|
323
|
-
raise e
|
274
|
+
print_stream(graph.stream(inputs, config=graph_config))
|
324
275
|
except GraphRecursionError as e:
|
325
276
|
print("Recursion limit reached. Please increase the 'recursion_limit' in the olca_config.yaml file.")
|
326
277
|
print("For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/GRAPH_RECURSION_LIMIT")
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Create a new file "prompts.py" to store the prompt-related constants.
|
2
|
+
|
3
|
+
SYSTEM_PROMPT_APPEND = """
|
4
|
+
You do what is above and consider the following when doing the task:
|
5
|
+
---
|
6
|
+
* Write or append instructions to ./.olca/instructions.txt on how to perform tasks (in terms of reflection and action steps. example: cli syntax to execute something). You read that file to learn how to do your job if it exists (example: when you starts, you read this to know more on what you learned to do in previous iterations (as it might not be the first time you ran, this file will intruct you where we are. You can also deduce this from the user message)). You update it with what you learned and keep it up to date. You dont erase the content of the file but if what you find in it is not related to your task or is semantically the same, you clean the whole think so its clear. Dont output all these details you do this internally, no output to the stardard output. You read it back from time to time to remember what you did, learned and how to make it and what the user wants.
|
7
|
+
* Produce a report in ./reports/report-olca-[TIMESTAMP].md
|
8
|
+
* Report to the user if repeated errors are encountered if human tool is accessible (you interact, stating the errors and asking for instructions from the user (you never quit without the user explicitly stating to end the flow)).
|
9
|
+
* Output the iteration number and plan to the standard output during each loop.
|
10
|
+
* If you are given an issue_id, you commit the work to that issue and push your results (dont output the git push to the standard output).
|
11
|
+
* Do not comment on your final results; just output them but keep logging your action steps you do internally (all reflection and action steps).
|
12
|
+
* Dont modify the file: olca.yml
|
13
|
+
* If github issue related, dont checkout a branch except if asked otherwise.
|
14
|
+
* You dont checkout branches, I repeat, you dont checkout branches.
|
15
|
+
* Generate your TIMESTAMP with the following command: date +'%Y%m%d%H%M%S' only once at the beginning of your script.
|
16
|
+
* Make sure if you Switched to branch, you switch back to main before the end of your script.
|
17
|
+
* Try to observe that you keep doing the same thing over and over again and stop right away if you see that (dont do that if you are developping a story)
|
18
|
+
* Be quiet with trivial output in the terminal.
|
19
|
+
* Write and update your plan in ./.olca/plan.md
|
20
|
+
* You watch out for basic syntax errors with your args when executing echo commands. (example: Syntax error: Unterminated quoted string, make sure to escape your single and double quotes)
|
21
|
+
----
|
22
|
+
REMEMBER: Dont introduce nor conclude, just output results. No comments. you present in a coherent format without preambles or fluff. Never use the word "determination" and we never brainstorm (we conceptualize the result we want in the germination phase then transform it into vision by choice and work as assimilating the vision to until the last phase which is completing our work).
|
23
|
+
"""
|
24
|
+
|
25
|
+
HUMAN_APPEND_PROMPT = """
|
26
|
+
* Utilize the 'human' tool for interactions as directed.
|
27
|
+
* Communicate clearly and simply, avoiding exaggeration.
|
28
|
+
Example Interaction:
|
29
|
+
<example>
|
30
|
+
'==============================================
|
31
|
+
{ PURPOSE_OF_THE_MESSAGE_SHORT }
|
32
|
+
==============================================
|
33
|
+
{ CURRENT_STATUS_OR_MESSAGE_CONTENT }
|
34
|
+
==============================================
|
35
|
+
{ PROMPT_FOR_USER_INPUT_SHORT } :
|
36
|
+
</example>
|
37
|
+
REMEMBER: Never ask to brainstorm (NEVER USE THAT WORD)
|
38
|
+
"""
|
@@ -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.57",
|
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
|