Skip to content

Commit

Permalink
Merge pull request #10 from Tachi-67/feature/add_api_configuration_he…
Browse files Browse the repository at this point in the history
…lper

Feature/add api configuration helper and remove unused helper functions
  • Loading branch information
nbaldwin98 authored Dec 27, 2023
2 parents db31634 + 2bea0f7 commit 9855d37
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 67 deletions.
124 changes: 63 additions & 61 deletions aiflows/utils/general_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,67 +425,6 @@ def read_yaml_file(path_to_file, resolve=True):
cfg = OmegaConf.to_container(cfg, resolve=resolve)
return cfg


def python_file_path_to_module_path(file_path):
"""Converts a python file path to a python module path
:param file_path: The python file path
:type file_path: str
:return: The python module path
:rtype: str
"""
return file_path.replace("/", ".").replace(".py", "")


def python_module_path_to_file_path(module_path):
"""Converts a python module path to a python file path
:param module_path: The python module path
:type module_path: str
:return: The python file path
:rtype: str
"""
return module_path.replace(".", "/") + ".py"


def extract_top_level_function_names(python_file_path):
"""Extracts the top level function names from a python file (ignores nested)
:param python_file_path: The path to the python file
:type python_file_path: str
:return: A list of function names
:rtype: List[str]
"""
function_names = []
with open(python_file_path, "r") as file:
file_content = file.read()
tree = ast.parse(file_content)

functions = filter(lambda node: isinstance(node, ast.FunctionDef), ast.iter_child_nodes(tree))
function_names = list(map(lambda node: node.name, functions))

return function_names


# def get_function_meta_data(function):
# """ Returns the meta data of a function. (docstring)"""
# return function_to_dict(function)


def get_function_from_name(function_name, module):
"""Returns a function from a module given its name."""
return getattr(module, function_name)


# def get_pyfile_functions_metadata_from_file(python_file_path):
# """ Returns the meta data of all the functions in a python file (docstring)"""
# function_names = extract_top_level_function_names(python_file_path)
# module_path = python_file_path_to_module_path(python_file_path)
# module = importlib.import_module(module_path)
# functions = [get_function_from_name(function_name, module) for function_name in function_names]
# return [get_function_meta_data(function) for function in functions]


def encode_image(image_path):
"""Encodes an image to base64."""
with open(image_path, "rb") as image_file:
Expand Down Expand Up @@ -524,3 +463,66 @@ def find_replace_in_dict(cfg, key_to_find, new_value,current_path=""):
elif isinstance(item, list):
cfg[key] = [find_replace_in_dict(x, key_to_find, new_value, new_path) for x in item]
return cfg

def quick_load(cfg, item, key="api_infos"):
"""Recursively loads the config item in a dictionary with key.
:param cfg: The dictionary to update
:type cfg: Dict[str, Any]
:param item: The item to set
:type item: Dict[str, Any]
:param key: The key to use, defaults to 'api_infos'
:type key: str, optional
example:
cfg = {
'backend': {
'api_infos': '???',
'model_name': {
'openai': 'gpt-4',
'azure': 'azure/gpt-4'
}
}
'Executor' : {
'subflows_config': {
'backend': {
'api_infos': '???',
'model_name': {
'openai': 'gpt-4',
'azure': 'azure/gpt-4'
}
}
}
}
}
api_information = [ApiInfo(backend_used="openai", api_key=os.getenv("OPENAI_API_KEY"))]
quick_load(cfg, api_information)
returns: cfg = {
'backend': {
'api_infos': [ApiInfo(backend_used="openai", api_key=os.getenv("OPENAI_API_KEY"))],
'model_name': {
'openai': 'gpt-4',
'azure': 'azure/gpt-4'
}
}
'Executor' : {
'subflows_config': {
'backend': {
'api_infos': [ApiInfo(backend_used="openai", api_key=os.getenv("OPENAI_API_KEY"))],
'model_name': {
'openai': 'gpt-4',
'azure': 'azure/gpt-4'
}
}
}
}
}
"""
if isinstance(cfg, dict):
if key in cfg and cfg[key] == "???":
cfg[key] = item
for k, v in cfg.items():
quick_load(v, item, key)
elif isinstance(cfg, list):
for elem in cfg:
quick_load(elem, item, key)

7 changes: 2 additions & 5 deletions examples/quick_start/runChatAtomicFlow.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from aiflows.backends.api_info import ApiInfo
from aiflows.utils.general_helpers import find_replace_in_dict
from aiflows.flow_launchers import FlowLauncher
from aiflows.backends.api_info import ApiInfo
from aiflows import flow_verse
import os
from aiflows import logging
from aiflows.utils.general_helpers import read_yaml_file
from aiflows.utils.general_helpers import read_yaml_file, quick_load


dependencies = [
Expand Down Expand Up @@ -37,7 +34,7 @@
cfg = read_yaml_file("flow_modules/aiflows/ChatFlowModule/demo.yaml")

# put the API information in the config
cfg["flow"]["backend"]["api_infos"] = api_information
quick_load(cfg, api_information, key="api_infos")

# ~~~ Instantiate the Flow ~~~
flow = ChatAtomicFlow.instantiate_from_default_config(**cfg["flow"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,14 @@ flow: # Overrides the ChatAtomicFlow config
The following overwrites the field with your personal API information:
```python
# put the API information in the config
# recursively find the 'api_infos' entry and put the API information in the config
quick_load(cfg, api_information, key="api_infos")
```
This is equivalent to the following:
```python
cfg["flow"]["backend"]["api_infos"] = api_information
```
However, with `quick_load`, we are able to quickly set all entries of api_infos, this is useful when we need to configure more than just one config entries.

Instantiate your Flow:
```python
Expand Down

0 comments on commit 9855d37

Please sign in to comment.