flo-ai 0.0.5.dev2__tar.gz → 0.0.5.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/PKG-INFO +6 -2
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/README.md +5 -1
- flo_ai-0.0.5.dev4/flo_ai/parsers/flo_json_parser.py +157 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/pyproject.toml +1 -1
- flo_ai-0.0.5.dev2/flo_ai/parsers/flo_json_parser.py +0 -61
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/LICENSE +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/builders/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/builders/yaml_builder.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/flo_callbacks.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/flo_execution_logger.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/README.md +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/flo_langchain_logger.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/flo_logger.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/common_constants.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/flo_node_contants.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/prompt_constants.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/core.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/error/flo_exception.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/factory/agent_factory.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/helpers/utils.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/delegate.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/exception.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_agent.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_delegation_agent.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_executable.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_llm_agent.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_member.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_node.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_reflection_agent.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_routed_team.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_team.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_tool_agent.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/parsers/flo_parser.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/parsers/flo_pydantic_parser.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_compression_pipeline.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_multi_query.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_retriever.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_linear.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_llm_router.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_router.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_router_factory.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_supervisor.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_data_collector.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_kv_collector.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_session.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_state.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/storage/data_collector.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/tools/__init__.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/tools/flo_tool.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/yaml/config.py +0 -0
- {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/yaml/validators.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flo-ai
|
|
3
|
-
Version: 0.0.5.
|
|
3
|
+
Version: 0.0.5.dev4
|
|
4
4
|
Summary: A easy way to create structured AI agents
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: vizsatiz
|
|
@@ -369,7 +369,11 @@ Built with ❤️ using:
|
|
|
369
369
|
<p><b>Build an Agentic RAG using FloAI in minutes</b><br />FloAI has just made implementing agentic RAG simple and easy to manage</p>
|
|
370
370
|
</a>
|
|
371
371
|
</div>
|
|
372
|
-
|
|
372
|
+
<a href="https://medium.com/rootflo/mastering-ai-interaction-logging-and-data-collection-with-floai-a490818bb2f1" target="_blank" style="text-decoration: none;">
|
|
373
|
+
<img src="./images/blog-image.png" width="150" style="border-radius: 10px;" />
|
|
374
|
+
<p><b>Mastering AI Interaction Logging and Data Collection with FloAI</b><br />Learn how to leverage FloAI's powerful logging system for debugging, training data generation, and system optimization</p>
|
|
375
|
+
</a>
|
|
376
|
+
</a>
|
|
373
377
|
---
|
|
374
378
|
|
|
375
379
|
<div align="center">
|
|
@@ -347,7 +347,11 @@ Built with ❤️ using:
|
|
|
347
347
|
<p><b>Build an Agentic RAG using FloAI in minutes</b><br />FloAI has just made implementing agentic RAG simple and easy to manage</p>
|
|
348
348
|
</a>
|
|
349
349
|
</div>
|
|
350
|
-
|
|
350
|
+
<a href="https://medium.com/rootflo/mastering-ai-interaction-logging-and-data-collection-with-floai-a490818bb2f1" target="_blank" style="text-decoration: none;">
|
|
351
|
+
<img src="./images/blog-image.png" width="150" style="border-radius: 10px;" />
|
|
352
|
+
<p><b>Mastering AI Interaction Logging and Data Collection with FloAI</b><br />Learn how to leverage FloAI's powerful logging system for debugging, training data generation, and system optimization</p>
|
|
353
|
+
</a>
|
|
354
|
+
</a>
|
|
351
355
|
---
|
|
352
356
|
|
|
353
357
|
<div align="center">
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import csv
|
|
3
|
+
from io import StringIO
|
|
4
|
+
from flo_ai.parsers.flo_parser import FloParser
|
|
5
|
+
from typing import List, Dict, Any, Optional, Literal
|
|
6
|
+
from pydantic import BaseModel, Field, create_model
|
|
7
|
+
from flo_ai.error.flo_exception import FloException
|
|
8
|
+
from langchain_core.output_parsers import PydanticOutputParser
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ParseContract:
|
|
14
|
+
name: str
|
|
15
|
+
fields: List[Dict[str, Any]]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FloJsonParser(FloParser):
|
|
19
|
+
def __init__(self, parse_contract: ParseContract):
|
|
20
|
+
self.contract = parse_contract
|
|
21
|
+
self._cached_models = {}
|
|
22
|
+
super().__init__()
|
|
23
|
+
|
|
24
|
+
def __dict_list_to_csv_string(self, data):
|
|
25
|
+
if not data or len(data) == 0:
|
|
26
|
+
return '```No data provided```'
|
|
27
|
+
headers = data[0].keys()
|
|
28
|
+
output = StringIO()
|
|
29
|
+
|
|
30
|
+
writer = csv.DictWriter(output, fieldnames=headers)
|
|
31
|
+
writer.writeheader()
|
|
32
|
+
writer.writerows(data)
|
|
33
|
+
|
|
34
|
+
csv_string = output.getvalue()
|
|
35
|
+
output.close()
|
|
36
|
+
|
|
37
|
+
return f'```\n{csv_string}```'
|
|
38
|
+
|
|
39
|
+
def __create_nested_model(
|
|
40
|
+
self, field_def: Dict[str, Any], model_name: str
|
|
41
|
+
) -> BaseModel:
|
|
42
|
+
"""Creates a nested Pydantic model for object types"""
|
|
43
|
+
if model_name in self._cached_models:
|
|
44
|
+
return self._cached_models[model_name]
|
|
45
|
+
|
|
46
|
+
nested_fields = {}
|
|
47
|
+
for nested_field in field_def['fields']:
|
|
48
|
+
nested_type = self.__get_field_type_annotation(
|
|
49
|
+
nested_field, f"{model_name}_{nested_field['name']}"
|
|
50
|
+
)
|
|
51
|
+
field_description = nested_field['description']
|
|
52
|
+
nested_fields[nested_field['name']] = (
|
|
53
|
+
nested_type,
|
|
54
|
+
Field(..., description=field_description),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
NestedModel = create_model(model_name, **nested_fields)
|
|
58
|
+
self._cached_models[model_name] = NestedModel
|
|
59
|
+
return NestedModel
|
|
60
|
+
|
|
61
|
+
def __get_field_type_annotation(
|
|
62
|
+
self, field: Dict[str, Any], model_name: str
|
|
63
|
+
) -> Any:
|
|
64
|
+
"""Determines the type annotation for a field, handling nested objects"""
|
|
65
|
+
type_mapping = {
|
|
66
|
+
'str': str,
|
|
67
|
+
'int': int,
|
|
68
|
+
'bool': bool,
|
|
69
|
+
'float': float,
|
|
70
|
+
'literal': self.__create_literal_type,
|
|
71
|
+
'object': lambda f: self.__create_nested_model(f, model_name),
|
|
72
|
+
'array': lambda f: List[
|
|
73
|
+
self.__get_field_type_annotation(f['items'], f'{model_name}_item')
|
|
74
|
+
],
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
field_type = field['type']
|
|
78
|
+
type_handler = type_mapping.get(field_type)
|
|
79
|
+
|
|
80
|
+
if type_handler is None:
|
|
81
|
+
raise ValueError(f'Unsupported type: {field_type}')
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
type_handler(field)
|
|
85
|
+
if field_type in ['literal', 'object', 'array']
|
|
86
|
+
else type_handler
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def __create_literal_type(self, field: Dict[str, Any]) -> Any:
|
|
90
|
+
"""Creates a Literal type from field definition"""
|
|
91
|
+
literal_values = field.get('values', [])
|
|
92
|
+
if not literal_values:
|
|
93
|
+
raise ValueError(
|
|
94
|
+
f"Field '{field['name']}' of type 'literal' must specify 'values'."
|
|
95
|
+
)
|
|
96
|
+
literals = [literal_value['value'] for literal_value in literal_values]
|
|
97
|
+
return Literal[tuple(literals)]
|
|
98
|
+
|
|
99
|
+
def __create_contract_from_json(self) -> BaseModel:
|
|
100
|
+
pydantic_fields = {}
|
|
101
|
+
for field in self.contract.fields:
|
|
102
|
+
field_type = self.__get_field_type_annotation(
|
|
103
|
+
field, f"{self.contract.name}_{field['name']}"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if field['type'] == 'literal':
|
|
107
|
+
literal_values = field.get('values', [])
|
|
108
|
+
default_prompt = field.get('default_value_prompt', '')
|
|
109
|
+
field_description = f"""
|
|
110
|
+
{field['description']}
|
|
111
|
+
Following are the list of possibles values and its correponding description:
|
|
112
|
+
{self.__dict_list_to_csv_string(literal_values)}
|
|
113
|
+
|
|
114
|
+
This should be one of the values in the `value` column in the above csv.
|
|
115
|
+
{default_prompt}
|
|
116
|
+
"""
|
|
117
|
+
else:
|
|
118
|
+
field_description = field['description']
|
|
119
|
+
|
|
120
|
+
pydantic_fields[field['name']] = (
|
|
121
|
+
field_type,
|
|
122
|
+
Field(..., description=field_description),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
DynamicModel = create_model(self.contract.name, **pydantic_fields)
|
|
126
|
+
return DynamicModel
|
|
127
|
+
|
|
128
|
+
def get_format_instructions(self):
|
|
129
|
+
return PydanticOutputParser(
|
|
130
|
+
pydantic_object=self.__create_contract_from_json()
|
|
131
|
+
).get_format_instructions()
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def create(json_dict: Optional[Dict] = None, json_path: Optional[str] = None):
|
|
135
|
+
return FloJsonParser.Builder(json_dict=json_dict, json_path=json_path).build()
|
|
136
|
+
|
|
137
|
+
class Builder:
|
|
138
|
+
def __init__(
|
|
139
|
+
self, json_dict: Optional[Dict] = None, json_path: Optional[str] = None
|
|
140
|
+
):
|
|
141
|
+
if json_dict is None and json_path is None:
|
|
142
|
+
raise FloException(
|
|
143
|
+
'Either of json_dict or json_path is required to build a FloJsonParser'
|
|
144
|
+
)
|
|
145
|
+
self.json_dict = json_dict
|
|
146
|
+
self.json_path = json_path
|
|
147
|
+
|
|
148
|
+
def build(self):
|
|
149
|
+
if self.json_dict:
|
|
150
|
+
name = self.json_dict['name']
|
|
151
|
+
fields = self.json_dict['fields']
|
|
152
|
+
else:
|
|
153
|
+
with open(self.json_path) as f:
|
|
154
|
+
json_contract = json.load(f)
|
|
155
|
+
name = json_contract['name']
|
|
156
|
+
fields = json_contract['fields']
|
|
157
|
+
return FloJsonParser(ParseContract(name=name, fields=fields))
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from flo_ai.parsers.flo_parser import FloParser
|
|
3
|
-
from typing import List, Dict, Any, Optional
|
|
4
|
-
from pydantic import BaseModel, Field, create_model
|
|
5
|
-
from flo_ai.error.flo_exception import FloException
|
|
6
|
-
from langchain_core.output_parsers import PydanticOutputParser
|
|
7
|
-
from dataclasses import dataclass
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class ParseContract:
|
|
12
|
-
name: str
|
|
13
|
-
fields: List[Dict[str, Any]]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class FloJsonParser(FloParser):
|
|
17
|
-
def __init__(self, parse_contract: ParseContract):
|
|
18
|
-
self.contract = parse_contract
|
|
19
|
-
super().__init__()
|
|
20
|
-
|
|
21
|
-
def __create_contract_from_json(self) -> BaseModel:
|
|
22
|
-
type_mapping = {'str': str, 'int': int, 'bool': bool, 'float': float}
|
|
23
|
-
pydantic_fields = {
|
|
24
|
-
field['name']: (
|
|
25
|
-
type_mapping[field['type']],
|
|
26
|
-
Field(..., description=field['description']),
|
|
27
|
-
)
|
|
28
|
-
for field in self.contract.fields
|
|
29
|
-
}
|
|
30
|
-
DynamicModel = create_model(self.contract.name, **pydantic_fields)
|
|
31
|
-
return DynamicModel
|
|
32
|
-
|
|
33
|
-
def get_format_instructions(self):
|
|
34
|
-
return PydanticOutputParser(
|
|
35
|
-
pydantic_object=self.__create_contract_from_json()
|
|
36
|
-
).get_format_instructions()
|
|
37
|
-
|
|
38
|
-
def create(json_dict: Optional[Dict] = None, json_path: Optional[str] = None):
|
|
39
|
-
return FloJsonParser.Builder(json_dict=json_dict, json_path=json_path).build()
|
|
40
|
-
|
|
41
|
-
class Builder:
|
|
42
|
-
def __init__(
|
|
43
|
-
self, json_dict: Optional[Dict] = None, json_path: Optional[str] = None
|
|
44
|
-
):
|
|
45
|
-
if json_dict is None and json_path is None:
|
|
46
|
-
raise FloException(
|
|
47
|
-
'Either of json_dict or json_path is required to build a FloJsonParser'
|
|
48
|
-
)
|
|
49
|
-
self.json_dict = json_dict
|
|
50
|
-
self.json_path = json_path
|
|
51
|
-
|
|
52
|
-
def build(self):
|
|
53
|
-
if self.json_dict:
|
|
54
|
-
name = self.json_dict['name']
|
|
55
|
-
fields = self.json_dict['fields']
|
|
56
|
-
else:
|
|
57
|
-
with open(self.json_path) as f:
|
|
58
|
-
json_contract = json.load(f)
|
|
59
|
-
name = json_contract['name']
|
|
60
|
-
fields = json_contract['fields']
|
|
61
|
-
return FloJsonParser(ParseContract(name=name, fields=fields))
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|