Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/common/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,22 @@ class Settings(BaseModel):
rag: Optional[RagSettings] = Field(default_factory=RagSettings, description="RAG Settings")
oci: Optional[OciSettings] = Field(default_factory=OciSettings, description="OCI Settings")

@classmethod
def from_json(cls, client: str, json: str):
"""Create instance from JSON or defaults, if JSON fails to validate"""
try:
tmp_settings = cls.model_validate_json(json)
tmp_settings.client = client
return tmp_settings
except ValueError as e:
return cls(client=client)


def json_to_file(self, settings_file: str):
"""Store settings to file at given path."""
with open(settings_file, 'w') as file:
settings_json = file.write(self.model_dump_json())


#####################################################
# Completions
Expand Down
33 changes: 32 additions & 1 deletion src/server/bootstrap/settings_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,45 @@

from common.schema import Settings
import common.logging_config as logging_config
import os

logger = logging_config.logging.getLogger("server.bootstrap.settings_def")

def _settings_path() -> str:
"""Return the path where settings should be stored.

It assumes that this module is in src/server/bootsrap and removes
"server/bootstrap/settings_def.py" from the path.
"""
src_dir_comps = __file__.split(os.sep)[:-3]
src_dir_comps.extend(["etc", "settings.json"])

return os.sep.join(src_dir_comps)


# SETTIGS_PATH is computed once the first time this module is loaded
SETTINGS_PATH = _settings_path()

def restore_or_default_settings(client: str, settings_file: str = SETTINGS_PATH) -> Settings:
"""Return a Settings instance restoring from JSON file or with default values.

Arguments
---------
client -- Client unique identifier
settings_file -- Path to the settings file with default value, but can be injected for testing
"""
if os.path.isfile(settings_file) and os.access(settings_file, os.R_OK):
with open(settings_file, 'r') as file:
settings_json = file.read()
else:
settings_json = ""
return Settings.from_json(client, settings_json)


def main() -> list[Settings]:
"""Define example Settings Support"""
clients = ["default", "server"]
settings_objects = [Settings(client=client) for client in clients]
settings_objects = [restore_or_default_settings(client=client) for client in clients]
return settings_objects


Expand Down
62 changes: 62 additions & 0 deletions tests/common/schema_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
Copyright (c) 2024, 2025, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
"""

from common.schema import Settings, LanguageModelParameters
import pytest
import unittest.mock as mock

def test_create_settings_from_json_returns_right_settings():
json = """
{ "client": "default",
"ll_model": { "context_length": null,
"frequency_penalty": 0.0,
"max_completion_tokens": 256,
"presence_penalty": 0.0,
"temperature": 1.2,
"top_p": 1.0,
"streaming": false,
"model": null,
"chat_history": true },
"prompts": { "ctx": "Basic Example",
"sys": "Basic Example" },
"rag": { "database": "DEFAULT",
"vector_store": null,
"alias": null,
"model": null,
"chunk_size": null,
"chunk_overlap": null,
"distance_metric": null,
"index_type": null,
"rag_enabled": false,
"grading": true,
"search_type": "Similarity",
"top_k": 4,
"score_threshold": 0.0,
"fetch_k": 20,
"lambda_mult": 0.5 },
"oci": { "auth_profile" :"DEFAULT" }
}
"""
client = "default"
settings_from_json = Settings.from_json(client, json)
some_settings = Settings(client=client)
some_settings.ll_model.temperature = 1.2
print(f"LEFT: {settings_from_json}")
print(f"RIGHT: {some_settings}")
assert settings_from_json == some_settings


def test_json_to_file_writes_settings_json():
client = "default"
path = 'some_path/some_file.json'
default_settings = Settings(client=client)
default_settings.ll_model.top_p = 0.5

mocked_open = mock.mock_open()
with mock.patch('builtins.open', mocked_open) as mock_open:
default_settings.json_to_file(path)
mock_open.assert_called_with(path, 'w')
mock_open().write.assert_called_once_with(default_settings.model_dump_json())

119 changes: 119 additions & 0 deletions tests/server/bootstrap/settings_def_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
Copyright (c) 2024, 2025, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
"""

from server.bootstrap.settings_def import restore_or_default_settings
from common.schema import Settings, LanguageModelParameters
import pytest
import os
import unittest.mock as mock


def test_restore_returns_default_settings_on_invalid_settings_file():
client = "default"
settings_from_json = restore_or_default_settings(client, "invalid_file.json")
default_settings = Settings(client=client)
assert settings_from_json == default_settings


@pytest.mark.parametrize(('is_file', 'has_access', 'file_read'),
[
(True, True, True),
(False, True, False),
(True, False, False),
(False, False, False),
])
@mock.patch('os.access')
@mock.patch('os.path.isfile')
def test_restore_reads_file_if_isfile_and_has_access(mock_isfile, mock_access, is_file, has_access, file_read):
client = "default"
path = 'some_path/some_file.json'
mock_isfile.return_value = is_file
mock_access.return_value = has_access
mocked_open = mock.mock_open(read_data="")
with mock.patch('builtins.open', mocked_open) as mock_open:
settings_from_file = restore_or_default_settings(client, path)
if file_read:
mock_open.assert_called_with(path, 'r')

mock_isfile.assert_called_with(path)
if is_file:
mock_access.assert_called_with(path, os.R_OK)


@mock.patch('os.access')
@mock.patch('os.path.isfile')
def test_restore_returns_default_settings_from_bad_json(mock_isfile, mock_access):
client = "default"
path = 'some_path/some_file.json'
json = """
{ "client": "default",
"prompts": { "ctx": "Another Example",
"sys": "Yet another Example" },
"nothing_else_here" }
"""
mock_isfile.return_value = True
mock_access.return_value = True
mocked_open = mock.mock_open(read_data=json)
with mock.patch('builtins.open', mocked_open) as mock_open:
settings_from_file = restore_or_default_settings(client, path)
mock_open.assert_called_with(path, 'r')

default_settings = Settings(client=client)

mock_isfile.assert_called_once_with(path)
mock_access.assert_called_once_with(path, os.R_OK)
assert settings_from_file == default_settings


@mock.patch('os.access')
@mock.patch('os.path.isfile')
def test_restore_returns_settings_from_json(mock_isfile, mock_access):
client = "default"
path = 'some_path/some_file.json'
json = """
{ "client": "default",
"ll_model": { "context_length": null,
"frequency_penalty": 0.0,
"max_completion_tokens": 256,
"presence_penalty": 0.0,
"temperature": 1.2,
"top_p": 1.0,
"streaming": false,
"model": null,
"chat_history": true },
"prompts": { "ctx": "Basic Example",
"sys": "Basic Example" },
"rag": { "database": "DEFAULT",
"vector_store": null,
"alias": null,
"model": null,
"chunk_size": null,
"chunk_overlap": null,
"distance_metric": null,
"index_type": null,
"rag_enabled": false,
"grading": true,
"search_type": "Similarity",
"top_k": 4,
"score_threshold": 0.0,
"fetch_k": 20,
"lambda_mult": 0.5 },
"oci": { "auth_profile" :"DEFAULT" }
}
"""
mock_isfile.return_value = True
mock_access.return_value = True
mocked_open = mock.mock_open(read_data=json)
with mock.patch('builtins.open', mocked_open) as mock_open:
settings_from_file = restore_or_default_settings(client, path)
mock_open.assert_called_with(path, 'r')

default_settings = Settings(client=client)
default_settings.ll_model.temperature = 1.2

mock_isfile.assert_called_once_with(path)
mock_access.assert_called_once_with(path, os.R_OK)
assert settings_from_file == default_settings