olca 0.2.63__py3-none-any.whl → 0.2.65__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
olca/fusewill_utils.py CHANGED
@@ -123,7 +123,7 @@ def list_traces_by_score(score_name, min_value=None, max_value=None, limit=100):
123
123
  return filtered_traces
124
124
 
125
125
  def add_score_to_a_trace(trace_id, generation_id, name, value, data_type="NUMERIC", comment=""):
126
- langfuse.score(
126
+ result_add_score_to_a_trace=langfuse.score(
127
127
  trace_id=trace_id,
128
128
  observation_id=generation_id,
129
129
  name=name,
@@ -131,11 +131,16 @@ def add_score_to_a_trace(trace_id, generation_id, name, value, data_type="NUMERI
131
131
  data_type=data_type,
132
132
  comment=comment
133
133
  )
134
+ return result_add_score_to_a_trace
134
135
 
135
136
  def create_score(name, data_type, description="", possible_values=None, min_value=None, max_value=None):
136
- langfuse.score(
137
+ placeholder_value = ""
138
+ if data_type.upper() == "BOOLEAN":
139
+ placeholder_value = "1"
140
+
141
+ resulting_score = langfuse.score(
137
142
  name=name,
138
- value="", # Provide a placeholder value
143
+ value=placeholder_value,
139
144
  data_type=data_type,
140
145
  description=description,
141
146
  # For categorical:
@@ -143,11 +148,17 @@ def create_score(name, data_type, description="", possible_values=None, min_valu
143
148
  # For numeric:
144
149
  **({"min_value": min_value, "max_value": max_value} if data_type == "NUMERIC" and min_value is not None and max_value is not None else {})
145
150
  )
151
+ return resulting_score
146
152
 
147
153
  def score_exists(name):
148
- scores = langfuse.get_scores()
149
- for score in scores.data:
150
- if score.name == name:
154
+ """
155
+ Check if a score with the given name exists by calling list_scores().
156
+ """
157
+ scores = list_scores()
158
+ if not scores or scores.get('meta', {}).get('totalItems', 0) == 0:
159
+ return False
160
+ for sc in scores:
161
+ if sc.get("name") == name:
151
162
  return True
152
163
  return False
153
164
 
@@ -265,7 +276,7 @@ def fetch_all_traces(start_date=None, end_date=None):
265
276
 
266
277
  def export_traces(format='json', output_path=None, start_date=None, end_date=None):
267
278
  """
268
- Export traces to a given format (json or csv).
279
+ Export traces along with their full score details.
269
280
  """
270
281
  try:
271
282
  all_traces = fetch_all_traces(start_date=start_date, end_date=end_date)
@@ -277,9 +288,23 @@ def export_traces(format='json', output_path=None, start_date=None, end_date=Non
277
288
  if output_dir and not os.path.exists(output_dir):
278
289
  os.makedirs(output_dir)
279
290
 
291
+ all_scores=list_scores()
292
+ exported_data = []
293
+ for t in all_traces:
294
+ # fetch full score details
295
+ score_details = []
296
+ if t.scores:
297
+ for s_id in t.scores:
298
+ s_detail = get_score_by_id(s_id)
299
+ if s_detail:
300
+ score_details.append(s_detail)
301
+ t_dict = t.__dict__
302
+ t_dict["score_details"] = score_details
303
+ exported_data.append(t_dict)
304
+
280
305
  if format == 'json':
281
306
  with open(output_path, 'w') as f:
282
- json.dump([t.__dict__ for t in all_traces], f, indent=2, default=str)
307
+ json.dump(exported_data, f, indent=2, default=str)
283
308
  elif format == 'csv':
284
309
  import csv
285
310
  fieldnames = ['id', 'name', 'input', 'output', 'createdAt']
@@ -299,7 +324,7 @@ def export_traces(format='json', output_path=None, start_date=None, end_date=Non
299
324
  # Sort traces by createdAt to ensure the oldest date is first
300
325
  all_traces.sort(key=lambda x: x.createdAt)
301
326
  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')
327
+ last_trace_date = datetime.datetime.fromisoformat(all_traces[-1].createdAt.replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M:%S')
303
328
  print(f"Traces exported to {output_path}. Total traces exported: {len(all_traces)}")
304
329
  print(f"Date range: {first_trace_date} to {last_trace_date}")
305
330
  else:
@@ -307,9 +332,29 @@ def export_traces(format='json', output_path=None, start_date=None, end_date=Non
307
332
  except Exception as e:
308
333
  print(f"Error exporting traces: {e}")
309
334
 
335
+ def create_new_trace(name, input_text, output_text, session_id=None, metadata=None, timestamp=None):
336
+ """
337
+ Creates a new trace with an optional timestamp.
338
+ """
339
+ parsed_timestamp = None
340
+ if timestamp:
341
+ try:
342
+ parsed_timestamp = datetime.datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
343
+ except ValueError:
344
+ pass
345
+ trace_created=langfuse.trace(
346
+ name=name,
347
+ input=input_text,
348
+ output=output_text,
349
+ session_id=session_id,
350
+ metadata=metadata,
351
+ timestamp=parsed_timestamp
352
+ )
353
+ return trace_created
354
+
310
355
  def import_traces(format='json', input_path=None):
311
356
  """
312
- Import traces from a given file (json or csv) into Langfuse.
357
+ Import traces. If any score doesn't exist, create it and attach it to the trace.
313
358
  """
314
359
  if not input_path:
315
360
  print("No input file provided for importing traces.")
@@ -327,14 +372,51 @@ def import_traces(format='json', input_path=None):
327
372
  for row in reader:
328
373
  data.append(row)
329
374
 
375
+ if isinstance(data, dict):
376
+ data = [data]
377
+
330
378
  # Create new traces in Langfuse from data
331
379
  for item in data:
332
- langfuse.create_trace(
380
+ trace_timestamp = item.get('timestamp') or item.get('createdAt')
381
+ new_trace = create_new_trace(
333
382
  name=item.get('name', 'Imported Trace'),
334
- input=item.get('input', ''),
335
- output=item.get('output', '')
336
- # pass other fields as needed
383
+ input_text=item.get('input', ''),
384
+ output_text=item.get('output', ''),
385
+ session_id=item.get('session_id'),
386
+ metadata=item.get('metadata'),
387
+ timestamp=trace_timestamp
337
388
  )
389
+ # handle imported scores
390
+ for s_detail in item.get("score_details", []):
391
+ score_name = s_detail["name"]
392
+ score_value = str(s_detail.get("value", "0"))
393
+ score_data_type = s_detail.get("dataType", "NUMERIC")
394
+ score_comment = s_detail.get("comment", "")
395
+ score_description = s_detail.get("description", "")
396
+ score_possible_values = s_detail.get("possible_values")
397
+ minimum_score_value = s_detail.get("min_value")
398
+ max_score_value = s_detail.get("max_value")
399
+ if not score_exists(score_name):
400
+ resulting_score=create_score(
401
+ name=score_name,
402
+ data_type=score_data_type,
403
+ description=score_description,
404
+ possible_values=score_possible_values,
405
+ min_value=minimum_score_value,
406
+ max_value=max_score_value
407
+
408
+ )
409
+ result_add_score_to_a_trace=add_score_to_a_trace(
410
+ trace_id=new_trace.id,
411
+ generation_id=None, # Replace as needed if your data includes observation IDs
412
+ name=score_name,
413
+ value=score_value,
414
+ data_type=score_data_type,
415
+ comment=score_comment
416
+ )
417
+ print(f"Added score {score_name} to trace {new_trace.id}")
418
+ print(result_add_score_to_a_trace)
419
+
338
420
  print(f"Imported {len(data)} traces from {input_path}")
339
421
  except Exception as e:
340
422
  print(f"Error importing traces: {e}")
olca/oiv.py ADDED
@@ -0,0 +1,145 @@
1
+ #!/bin/env python
2
+ #@STCGoal Create an agent callable with command line
3
+ #@STCIssue The original script was not callable from the command line.
4
+
5
+ from langchain import hub
6
+ from langchain.agents import AgentExecutor, create_react_agent
7
+ from langchain_community.agent_toolkits.load_tools import load_tools
8
+ from langchain_openai import ChatOpenAI
9
+ import argparse
10
+ import os
11
+ import json
12
+ import tlid
13
+ import warnings
14
+
15
+ warnings.filterwarnings("ignore", message="The function `loads` is in beta. It is actively being worked on, so the API may change.")
16
+ DEBUG_MODE=False
17
+
18
+ prompt=None
19
+ def _create_agent_tools(tool_name = "arxiv",temperature = 0.0,tool_hub_tag = "jgwill/react",chatbot_model = "gpt-4o-mini"):
20
+ global prompt
21
+
22
+ llm = ChatOpenAI(temperature=temperature,name=chatbot_model)
23
+
24
+ tools = load_tools(
25
+ [tool_name],
26
+ )
27
+ if DEBUG_MODE:
28
+
29
+ print("Tools:")
30
+ print(tools)
31
+ print("--------------")
32
+ prompt = hub.pull(tool_hub_tag)
33
+
34
+ if DEBUG_MODE:
35
+ print("prompt:")
36
+ print(prompt)
37
+ print("--------------")
38
+
39
+ agent = create_react_agent(llm, tools, prompt)
40
+
41
+ if DEBUG_MODE:
42
+ print("Agent:")
43
+ print(agent)
44
+ print("--------------")
45
+ return tools,agent
46
+
47
+
48
+ def create_agent_executor(tools, agent) -> AgentExecutor:
49
+ return AgentExecutor(agent=agent, tools=tools, verbose=True,handle_parsing_errors=True)
50
+
51
+
52
+
53
+
54
+ # tools, agent=_create_agent_tools()
55
+
56
+ # agent_executor=create_agent_executor(tools, agent)
57
+ def ask_agent(input_request, agent_executor=None,tool_hub_tag = "jgwill/react",chatbot_model = "gpt-4o-mini"):
58
+ if agent_executor is None:
59
+ tools, agent = _create_agent_tools(tool_hub_tag=tool_hub_tag)
60
+ agent_executor = create_agent_executor(tools, agent)
61
+
62
+ resp = agent_executor.invoke(
63
+ {
64
+ "input": input_request,
65
+ }
66
+ )
67
+
68
+ return resp
69
+
70
+ def serialize_response_to_json(resp):
71
+ return json.dumps(resp)
72
+
73
+ def serialize_response_to_json_file(resp, filename):
74
+ json_str=serialize_response_to_json(resp)
75
+ with open(filename, 'w') as f:
76
+ f.write(json_str)
77
+
78
+ def serialize_response_to_markdown(o):
79
+ output=o["output"]["output"]
80
+ string_md="# Output\n"
81
+ #string_md+=f"## Model\n{o['model']}\n"
82
+ #string_md+=f"## Prompt\n{o['prompt']['prompt']}\n"
83
+ string_md+=f"## Input\n{o['input']}\n"
84
+ string_md+=f"## Output\n{output}\n"
85
+ return string_md
86
+
87
+ def serialize_response_to_markdown_file(o, filename):
88
+ string_md=serialize_response_to_markdown(o)
89
+ with open(filename, 'w') as f:
90
+ f.write(string_md)
91
+
92
+
93
+ def main():
94
+ global prompt
95
+ args = parse_cli_arguments()
96
+
97
+ input_request = args.input
98
+ tool_hub_tag = "jgwill/react" if args.hub_tag is None else args.hub_tag
99
+ resp = ask_agent(input_request,tool_hub_tag=tool_hub_tag,chatbot_model=args.chatbot_model)
100
+ outdir=os.path.join(os.getcwd(),"output")
101
+ os.makedirs(outdir, exist_ok=True)
102
+ out_filename = f"{args.prefix}output-{tlid.get_minutes()}.json"
103
+ outfile=os.path.join(outdir,out_filename)
104
+ o={}
105
+ prompt_dict = {
106
+ "promptdata": str(prompt)
107
+ }
108
+ o["model"]=args.chatbot_model
109
+ o["prompt"]=prompt_dict
110
+ o["input"]=input_request
111
+ o["output"]=resp["output"]
112
+ serialize_response_to_json_file(o, outfile)
113
+ serialize_response_to_markdown_file(o, outfile.replace(".json",".md"))
114
+ VERBOSE_RESULT=False
115
+ if VERBOSE_RESULT:
116
+ print("==================================")
117
+ print(input_request)
118
+ print("============RESPONSE============")
119
+ print(resp)
120
+ print("==================================")
121
+ print("=============INPUT Request=====================")
122
+ print(input_request)
123
+ print("==================================")
124
+ print("============OUTPUT============")
125
+ output=resp["output"]
126
+ print(output)
127
+
128
+ def parse_cli_arguments():
129
+ parser = argparse.ArgumentParser(description='Process Input request for pattern search.')
130
+ parser.add_argument('-I','--input', type=str,
131
+ help='an input request for the searched article')
132
+ ##--hub_tag
133
+ parser.add_argument('-H','-ht','--hub_tag', type=str,
134
+ help='The hub tag for the process',default="jgwill/react")
135
+ #--chatbot_model
136
+ parser.add_argument('-M','-m','--chatbot_model', type=str,
137
+ help='a chatbot model for the processing',default="gpt-4o-mini")
138
+ #--prefix
139
+ parser.add_argument('-P','-p','--prefix', type=str,
140
+ help='a file prefix for output',default="arxiv-")
141
+ args = parser.parse_args()
142
+ return args
143
+
144
+ if __name__ == "__main__":
145
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: olca
3
- Version: 0.2.63
3
+ Version: 0.2.65
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,14 +1,15 @@
1
1
  olca/__init__.py,sha256=3QyLLAys_KiiDIe-cfO_7QyY7di_qCaCS-sVziW2BOw,23
2
2
  olca/fusewill_cli.py,sha256=7etgdpM64-jXGLlALG7PtwICAzoLKYGMBRvHf5nMLic,17119
3
- olca/fusewill_utils.py,sha256=LEKEDboyCm14_yvypE6lTed9j_uJN4K8vVdvYi6JoJs,14903
3
+ olca/fusewill_utils.py,sha256=sNCe4LhpSaEOY5olMxW1nTv7CKiT__dc2lGomelE6mY,18207
4
+ olca/oiv.py,sha256=A1YXzHV0smUONPHG_BH-RxXOg3rsWVWY07klLFCHdjE,4627
4
5
  olca/olcacli.py,sha256=oftilrp9v0QOV5tJeb6o8nwO54gjjlwWVfDU5JpoXJc,10758
5
6
  olca/olcahelper.py,sha256=s9KwEYAJCbnKSXIsj5HCL-OHxkSsmL08ZBgoluxmP1s,3828
6
7
  olca/prompts.py,sha256=q7lvDZ8n_K6ea2nu3K5R2fgBgQYrCIEjh0cA9fUlMFI,3697
7
8
  olca/tracing.py,sha256=GSuXIKmIMQ9V2gLkKcin142Z2QpyS6obsnj8Tf-1zHc,1621
8
9
  olca/utils.py,sha256=zM94HDMDYF95Yd9ubeOK6vuepbQN4kDFh0rTvaVFagI,912
9
- olca-0.2.63.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
10
- olca-0.2.63.dist-info/METADATA,sha256=67fTWBnjePdUpuwRp-xJ1lRFjHYj1HZhwbxtnRm9g0Q,25808
11
- olca-0.2.63.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
12
- olca-0.2.63.dist-info/entry_points.txt,sha256=AhP5FMv6vnOq9C76V_vxRVIO50smnZXG4RIY47oD2_U,103
13
- olca-0.2.63.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
14
- olca-0.2.63.dist-info/RECORD,,
10
+ olca-0.2.65.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
11
+ olca-0.2.65.dist-info/METADATA,sha256=T8KELtV1Ow3bmgtlbu2I_hoeFgns1wa8XMabWimuLsg,25808
12
+ olca-0.2.65.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
13
+ olca-0.2.65.dist-info/entry_points.txt,sha256=W2UkinpMZYsCLH54must9ahwbzCRl-rekcZ7rL5u3wA,123
14
+ olca-0.2.65.dist-info/top_level.txt,sha256=bGDtAReS-xlS0F6MM-DyD0IQUqjNdWmgemnM3vNtrpI,5
15
+ olca-0.2.65.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  [console_scripts]
2
2
  fusewill = olca.fusewill_cli:main
3
+ oiv = olca.oiv:main
3
4
  olca = olca.olcacli:main
4
5
  olca2 = olca.olcacli:main
File without changes
File without changes