You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+41-10Lines changed: 41 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
# Optify
4
4
5
-
Simplifies**configuration driven development**: getting the right configuration options for a process or request using pre-loaded configurations from files (JSON, YAML, etc.) to manage options for feature flags, experiments, or flights.
5
+
Powers**configuration driven development**: getting the right configuration options for a process or request using pre-loaded configurations from files (JSON, YAML, etc.) to manage options for feature flags, experiments, or flights.
6
6
Configurations for different experiments or feature flags are mergeable to support multiple experiments or feature flags for the same request.
@@ -15,11 +15,14 @@ Configurations for different experiments or feature flags are mergeable to suppo
15
15
> The configuration should declare **what** to do, but **not how** to do it.
16
16
17
17
This project helps improve the scalability and maintainability of code.
18
-
We should determine the right configuration for a request or process when it starts by passing the enabled features to an `OptionsProvider`.
18
+
Determine the right configuration for a request or process when it starts by passing the enabled features to an `OptionsProvider`.
19
19
The returned options would be used throughout the request or process to change business logic.
20
20
Supporting deep configurations with many types of properties instead of simple enabled/disabled feature flags is important to help avoid conditional statements (`if` statements) and thus improve the scalability of our code and make it easier to maintain our code as explained in [this article][cond-article].
21
21
22
-
Instead of working with feature flags:
22
+
See [AI Example](./docs/AI_Example.md) for an example of using Optify to manage the configuration for using an LLM with customizing the system instructions and enabled tools.
23
+
24
+
## Motivation
25
+
Instead of working with feature flags like this:
23
26
```Python
24
27
if Settings.is_feature_A_enabled:
25
28
handle_A(params)
@@ -45,7 +48,7 @@ Instead we can convert each enabled flag to a string and then build the merged c
45
48
46
49
See [tests](./tests/) for examples and tests for different variations of this paradigm for managing options.
47
50
48
-
Core Features:
51
+
## Core Features
49
52
***Each *feature flag* can be represented by a JSON or YAML file** which contains options to override default configuration values when processing feature names or experiment names in a request.
50
53
* Each file is a granular **partial** representation of the overall configuration.
51
54
Features are intended to be combined to build the final configuration.
@@ -82,10 +85,35 @@ Configurations in the cloud are fine for temporary experiments, but make the dai
82
85
The main point is to keep the configurations private and internal to your codebase while feature flags names are part of your external API.
83
86
84
87
# Merging Configuration Files
85
-
When merging configurations for features, objects are merged with the last feature taking precedence.
86
-
Key values, including lists are overwritten.
88
+
Objects are merged with the last feature taking precedence.
89
+
**All values, including arrays/lists, but not objects/dictionaries, are overwritten.**
90
+
I.e., all types override previous values except for objects/dictionaries which are merged recursively.
91
+
92
+
**Array items are not overwritten** because it would make it impossible or confusing to insert items or remove items.
93
+
To replicate an array that needs configurable items, use an object with keys to sort and treat `null` values as removed items.
94
+
For example, consider this configuration built after merging others:
95
+
```JSON
96
+
{
97
+
"items": {
98
+
"item_01": {"k": "value 1"},
99
+
"item_03": null,
100
+
"item_05": {"k": "value 5"}
101
+
}
102
+
}
103
+
```
104
+
105
+
It represents an array: `[{"k": "value 1"}, {"k": "value 5"}]`
106
+
107
+
The following Python code can be used to filter, sort, and convert it to the dictionary to a list:
108
+
```Python
109
+
items =sorted(
110
+
((k,v) for k, v in config["items"].items() if v isnotNone),
111
+
key=lambdakv: kv[0])
112
+
items = [v for (_k,v) in items]
113
+
```
114
+
87
115
88
-
As explained below, the .NET version works a little differently that the versions in this repository which are backed by the Rust implementation.
116
+
As explained below, the .NET version works a little differently than the versions in this repository which are backed by the Rust implementation.
89
117
90
118
## Example
91
119
Suppose you have a class that you want to use to configure your logic at runtime:
0 commit comments