nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: caikit/caikit
Pull request #55 (2023-04-21 18:13:59)

🐛 fix none output type
We don't want to throw in service generation even if the output type is not a DM object. 


Patch:
diff --git a/caikit/runtime/service_generation/primitives.py b/caikit/runtime/service_generation/primitives.py
index 929e2eb0..00c9d050 100644
--- a/caikit/runtime/service_generation/primitives.py
+++ b/caikit/runtime/service_generation/primitives.py
@@ -106,8 +106,10 @@ def extract_data_model_type_from_union(arg_type: Type) -> Type:
             )
             return extract_data_model_type_from_union(dm_types[0])
 
-    # anything else is an invalid output type
-    raise RuntimeError(f"Invalid arg type for output : {arg_type}")
+    # if it's anything else we just return as is
+    # we don't actually want to throw errors from service generation
+    log.warning("Return type [%s] not a DM type, returning as is", arg_type)
+    return arg_type
 
 
 def is_primitive_method(


Test patch:
diff --git a/tests/runtime/service_generation/test_primitives.py b/tests/runtime/service_generation/test_primitives.py
index 66e78024..9d128839 100644
--- a/tests/runtime/service_generation/test_primitives.py
+++ b/tests/runtime/service_generation/test_primitives.py
@@ -11,6 +11,14 @@ from caikit.runtime.service_generation.primitives import (
 from sample_lib.data_model import SampleOutputType
 
 
+def test_to_output_dm_type_with_None():
+    assert extract_data_model_type_from_union(None) == None
+
+
+def test_to_output_dm_type_with_raw_primitive():
+    assert extract_data_model_type_from_union(str) == str
+
+
 def test_to_output_dm_type_with_dm():
     assert extract_data_model_type_from_union(SampleOutputType) == SampleOutputType
 
@@ -27,8 +35,3 @@ def test_to_output_dm_type_with_union_optional_dm():
         extract_data_model_type_from_union(Union[Optional[SampleOutputType], str])
         == SampleOutputType
     )
-
-
-def test_to_output_dm_type_raises_primitive():
-    with pytest.raises(RuntimeError):
-        extract_data_model_type_from_union(str)
Repository: caikit/caikit
Pull request #95 (2023-05-04 22:35:25)

FixEnumDeref: When converting an Enum value to a serialized format, d…
…ereference it


Patch:
diff --git a/caikit/core/data_model/base.py b/caikit/core/data_model/base.py
index 4fcef269..eb52854a 100644
--- a/caikit/core/data_model/base.py
+++ b/caikit/core/data_model/base.py
@@ -20,6 +20,7 @@
 # pylint: disable=no-member
 
 # Standard
+from enum import Enum
 from typing import Optional, Type, Union
 import base64
 import json
@@ -560,9 +561,13 @@ class DataBase(metaclass=_DataBaseMetaClass):
             if attr is None:
                 continue
 
-            if field in self._fields_primitive or field in self._fields_enum:
+            if field in self._fields_primitive:
                 setattr(proto, field, attr)
-
+            elif field in self._fields_enum:
+                if isinstance(attr, Enum):
+                    setattr(proto, field, attr.value)
+                else:
+                    setattr(proto, field, attr)
             elif field in self._fields_map:
                 subproto = getattr(proto, field)
                 for key, value in attr.items():
@@ -649,7 +654,9 @@ class DataBase(metaclass=_DataBaseMetaClass):
             # if field is an enum, do the reverse lookup from int -> str
             enum_rev = self.fields_enum_rev.get(field)
             if enum_rev is not None:
-                return enum_rev[attr]
+                return (
+                    enum_rev[attr.value] if isinstance(attr, Enum) else enum_rev[attr]
+                )
 
         if field in self._fields_enum_repeated:
             # if field is an enum, do the reverse lookup from int -> str


Test patch:
diff --git a/tests/core/data_model/test_dataobject.py b/tests/core/data_model/test_dataobject.py
index 41e8668b..593366f8 100644
--- a/tests/core/data_model/test_dataobject.py
+++ b/tests/core/data_model/test_dataobject.py
@@ -669,3 +669,31 @@ def test_dataobject_dataclass_default_factory():
     inst = Foo()
     assert inst.foo is not None
     assert inst.foo == []
+
+
+def test_enum_value_dereference():
+    """Make sure that enum value objects can be used to instantiate data model
+    objects and that they are correctly dereferenced in to_proto, to_dict, and
+    to_json
+    """
+
+    @dataobject
+    class FooEnum(Enum):
+        FOO = 1
+        BAR = 2
+
+    @dataobject
+    class Foo(DataObjectBase):
+        foo: FooEnum
+
+    # Create an instance with an enum value object
+    inst = Foo(foo=FooEnum.FOO)
+    assert inst.to_proto().foo == FooEnum.FOO.value
+    assert inst.to_dict()["foo"] == FooEnum.FOO.name
+    assert json.loads(inst.to_json())["foo"] == FooEnum.FOO.name
+
+    # Create an instance with an integer value
+    inst = Foo(foo=FooEnum.FOO.value)
+    assert inst.to_proto().foo == FooEnum.FOO.value
+    assert inst.to_dict()["foo"] == FooEnum.FOO.name
+    assert json.loads(inst.to_json())["foo"] == FooEnum.FOO.name
Repository: caikit/caikit
Pull request #98 (2023-05-09 18:20:40)

🐛 handle ctrl chars in datastream
Handle escaped control characters in the server while loading training data.

The current code handles control characters as part of the string, for example `"name \t ": "John"` works well. But introducing new line characters as part of a `jsonl` file is what's causing problems at the moment.


Patch:
diff --git a/caikit/core/data_model/streams/data_stream.py b/caikit/core/data_model/streams/data_stream.py
index ec332375..34d6c614 100644
--- a/caikit/core/data_model/streams/data_stream.py
+++ b/caikit/core/data_model/streams/data_stream.py
@@ -176,7 +176,8 @@ class DataStream(Generic[T]):
 
                 try:
                     for line in lines:
-                        yield json.loads(line)
+                        if line.strip():  # ignore empty lines
+                            yield json.loads(line)
                 except json.JSONDecodeError as e:
                     error(
                         "<COR55596551E>",


Test patch:
diff --git a/tests/core/data_model/streams/test_data_stream.py b/tests/core/data_model/streams/test_data_stream.py
index fcf70ec2..86bcb8b7 100644
--- a/tests/core/data_model/streams/test_data_stream.py
+++ b/tests/core/data_model/streams/test_data_stream.py
@@ -87,6 +87,9 @@ class TestDataStream(TestCaseBase):
         self.jsonl_data_stream = core_dm.DataStream.from_jsonl(
             os.path.join(self.samples_path, "sample.jsonl")
         )
+        self.jsonl_w_control_chars_data_stream = core_dm.DataStream.from_jsonl(
+            os.path.join(self.samples_path, "control_chars.jsonl")
+        )
         self.sample_type_data_stream = self.txt_data_stream.map(
             lambda text: SampleInputType(name=text)
         )
@@ -155,6 +158,12 @@ class TestDataStream(TestCaseBase):
             for element in data_item:
                 self.assertIsInstance(element, str)
 
+    def test_jsonl_control_chars_array_data_stream(self):
+        self.validate_data_stream(self.jsonl_w_control_chars_data_stream, 2, dict, 2)
+        for data_item in self.jsonl_data_stream:
+            for element in data_item:
+                self.assertIsInstance(element, str)
+
     def test_bad_json_stream(self):
         with self.assertRaisesRegex(ValueError, "Invalid JSON object"):
             next(iter(core_dm.DataStream.from_json_array(self.bad_json)))
diff --git a/tests/fixtures/data_stream_inputs/control_chars.jsonl b/tests/fixtures/data_stream_inputs/control_chars.jsonl
new file mode 100644
index 00000000..8a31745f
--- /dev/null
+++ b/tests/fixtures/data_stream_inputs/control_chars.jsonl
@@ -0,0 +1,3 @@
+{"name \t": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
+
+{"name \n": "John", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
Repository: caikit/caikit
Pull request #121 (2023-05-17 19:13:26)

:bug: Fix request creation with optional params 
Requests with optional parameters were not getting generated


Patch:
diff --git a/caikit/runtime/service_generation/rpcs.py b/caikit/runtime/service_generation/rpcs.py
index ffaf8a86..e058eb43 100644
--- a/caikit/runtime/service_generation/rpcs.py
+++ b/caikit/runtime/service_generation/rpcs.py
@@ -78,7 +78,7 @@ class CaikitRPCBase(abc.ABC):
         attrs = copy.copy(self.request.default_map)
         attrs["__annotations__"] = {**properties, **optional_properties}
 
-        if not properties and optional_properties:
+        if not properties and not optional_properties:
             log.warning(
                 "No arguments found for request %s. Cannot generate rpc",
                 self.request.name,


Test patch:
diff --git a/tests/runtime/service_generation/test_rpcs.py b/tests/runtime/service_generation/test_rpcs.py
new file mode 100644
index 00000000..5f9dfc82
--- /dev/null
+++ b/tests/runtime/service_generation/test_rpcs.py
@@ -0,0 +1,51 @@
+# Copyright The Caikit Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tests for the rpc objects that hold our in-memory representation of
+what an RPC for a service looks like"""
+# Standard
+import uuid
+
+# Local
+from caikit.core import BlockBase, TaskBase
+from caikit.runtime.service_generation.rpcs import TaskPredictRPC
+from caikit.runtime.service_generation.signature_parsing import (
+    CaikitCoreModuleMethodSignature,
+)
+from sample_lib.data_model import SampleOutputType, SampleTask
+import caikit.core
+
+
+def test_task_inference_rpc_with_all_optional_params():
+    @caikit.core.task(
+        required_parameters={"str_val": str}, output_type=SampleOutputType
+    )
+    class TestTask(TaskBase):
+        pass
+
+    @caikit.core.block(
+        id=str(uuid.uuid4()), name="testest", version="9.9.9", task=SampleTask
+    )
+    class TestBlock(BlockBase):
+        def run(self, str_val="I have a default"):
+            pass
+
+    rpc = TaskPredictRPC(
+        task=("foo", "bar"),
+        method_signatures=[CaikitCoreModuleMethodSignature(TestBlock, "run")],
+        primitive_data_model_types=[],
+    )
+
+    data_model = rpc.create_request_data_model(package_name="blah")
+    assert data_model is not None
Repository: caikit/caikit
Pull request #141 (2023-05-24 20:44:16)

:bug: put default load impl back
For @gkumbhat

This puts back the old workflow base load as the module base load, so users that implement only `_load` aren't broken


Patch:
diff --git a/caikit/core/modules/base.py b/caikit/core/modules/base.py
index 22990556..44c534e0 100644
--- a/caikit/core/modules/base.py
+++ b/caikit/core/modules/base.py
@@ -39,6 +39,7 @@ import alog
 from ..data_model import DataBase, DataStream
 from ..toolkit import fileio
 from ..toolkit.errors import DataValidationError, error_handler
+from .loader import ModuleLoader
 from .meta import _ModuleBaseMeta
 from caikit import core
 
@@ -106,12 +107,17 @@ class ModuleBase(metaclass=_ModuleBaseMeta):
 
     @classmethod
     @alog.logged_function(log.debug)
-    def load(cls, *args, **kwargs):
-        """Load a model."""
-        error(
-            "<COR92634437E>",
-            NotImplementedError("This is not available in this module."),
-        )
+    def load(cls, model_path, *args, **kwargs):
+        """Load a new instance of workflow from a given model_path
+
+        Args:
+            model_path: str
+                Path to workflow
+        Returns:
+            caikit.core.workflows.base.WorkflowBase
+                A new instance of any given implementation of WorkflowBase
+        """
+        return cls._load(ModuleLoader(model_path), *args, **kwargs)
 
     @classmethod
     def _load(cls, module_loader, *args, **kwargs):


Test patch:
diff --git a/tests/core/modules/test_module.py b/tests/core/modules/test_module.py
index 4a55434d..2c930520 100644
--- a/tests/core/modules/test_module.py
+++ b/tests/core/modules/test_module.py
@@ -21,10 +21,9 @@ import tempfile
 import aconfig
 
 # Local
-from caikit.core import ModuleConfig
+from caikit.core import ModuleConfig, ModuleLoader
 from caikit.core.module_backends.module_backend_config import configured_load_backends
 from caikit.core.modules.decorator import SUPPORTED_LOAD_BACKENDS_VAR_NAME
-from caikit.core.registries import module_backend_registry
 
 # pylint: disable=import-error
 from sample_lib.data_model.sample import SampleInputType
@@ -98,9 +97,20 @@ def test_init_available():
     assert isinstance(model, caikit.core.ModuleBase)
 
 
-def test_load_not_implemented():
+def test_underscore_load_not_implemented():
     with pytest.raises(NotImplementedError):
-        caikit.core.ModuleBase.load()
+        caikit.core.ModuleBase._load(None)
+
+
+def test_load_delegates_to_underscore_load(good_model_path):
+    @caikit.core.modules.module(id="blah", name="dummy base", version="0.0.1")
+    class DummyFoo(caikit.core.ModuleBase):
+        @classmethod
+        def _load(cls, module_loader, **kwargs):
+            assert isinstance(module_loader, ModuleLoader)
+            return "foo"
+
+    assert DummyFoo.load(good_model_path) == "foo"
 
 
 def test_run_not_implemented(base_module_instance):