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.
Files changed (59) hide show
  1. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/PKG-INFO +6 -2
  2. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/README.md +5 -1
  3. flo_ai-0.0.5.dev4/flo_ai/parsers/flo_json_parser.py +157 -0
  4. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/pyproject.toml +1 -1
  5. flo_ai-0.0.5.dev2/flo_ai/parsers/flo_json_parser.py +0 -61
  6. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/LICENSE +0 -0
  7. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/__init__.py +0 -0
  8. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/builders/__init__.py +0 -0
  9. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/builders/yaml_builder.py +0 -0
  10. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/__init__.py +0 -0
  11. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/flo_callbacks.py +0 -0
  12. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/callbacks/flo_execution_logger.py +0 -0
  13. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/README.md +0 -0
  14. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/__init__.py +0 -0
  15. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/flo_langchain_logger.py +0 -0
  16. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/common/flo_logger.py +0 -0
  17. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/__init__.py +0 -0
  18. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/common_constants.py +0 -0
  19. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/flo_node_contants.py +0 -0
  20. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/constants/prompt_constants.py +0 -0
  21. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/core.py +0 -0
  22. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/error/flo_exception.py +0 -0
  23. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/factory/agent_factory.py +0 -0
  24. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/helpers/utils.py +0 -0
  25. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/__init__.py +0 -0
  26. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/delegate.py +0 -0
  27. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/exception.py +0 -0
  28. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_agent.py +0 -0
  29. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_delegation_agent.py +0 -0
  30. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_executable.py +0 -0
  31. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_llm_agent.py +0 -0
  32. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_member.py +0 -0
  33. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_node.py +0 -0
  34. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_reflection_agent.py +0 -0
  35. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_routed_team.py +0 -0
  36. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_team.py +0 -0
  37. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/models/flo_tool_agent.py +0 -0
  38. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/parsers/flo_parser.py +0 -0
  39. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/parsers/flo_pydantic_parser.py +0 -0
  40. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/__init__.py +0 -0
  41. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_compression_pipeline.py +0 -0
  42. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_multi_query.py +0 -0
  43. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/retrievers/flo_retriever.py +0 -0
  44. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/__init__.py +0 -0
  45. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_linear.py +0 -0
  46. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_llm_router.py +0 -0
  47. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_router.py +0 -0
  48. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_router_factory.py +0 -0
  49. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/router/flo_supervisor.py +0 -0
  50. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/__init__.py +0 -0
  51. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_data_collector.py +0 -0
  52. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_kv_collector.py +0 -0
  53. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_session.py +0 -0
  54. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/state/flo_state.py +0 -0
  55. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/storage/data_collector.py +0 -0
  56. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/tools/__init__.py +0 -0
  57. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/tools/flo_tool.py +0 -0
  58. {flo_ai-0.0.5.dev2 → flo_ai-0.0.5.dev4}/flo_ai/yaml/config.py +0 -0
  59. {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.dev2
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,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "flo-ai"
3
- version = "0.0.5-dev2"
3
+ version = "0.0.5-dev4"
4
4
  description = "A easy way to create structured AI agents"
5
5
  authors = ["vizsatiz <vishnu@rootfor.xyz>"]
6
6
  license = "MIT"
@@ -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