Repository: caikit/caikit
Pull request #351 (2023-07-21 16:10:18)

:sparkles::white_check_mark: Use text for text generation task
For trying to move caikit-nlp text generation modules to use the prescribed interfaces and tasks for text generation per `caikit.interfaces.nlp` in https://github.com/caikit/caikit-nlp/issues/92, tests can be moved here and `inputs` was presumably used to conform with Huggingface interfaces. However for semantically meaningful use, the modules have all used `text` as the input. With the REST server, `inputs` will be usable to align with Huggingface interfaces.



Patch:
diff --git a/caikit/interfaces/nlp/tasks.py b/caikit/interfaces/nlp/tasks.py
index 0730e032..3321467c 100644
--- a/caikit/interfaces/nlp/tasks.py
+++ b/caikit/interfaces/nlp/tasks.py
@@ -24,7 +24,7 @@ from .data_model.text_generation import GeneratedTextResult, GeneratedTextStream
 
 
 @task(
-    unary_parameters={"inputs": str},
+    unary_parameters={"text": str},
     unary_output_type=GeneratedTextResult,
     streaming_output_type=Iterable[GeneratedTextStreamResult],
 )


Test patch:
diff --git a/tests/interfaces/nlp/test_nlp_tasks.py b/tests/interfaces/nlp/test_nlp_tasks.py
index f5be53bd..6f3305d5 100644
--- a/tests/interfaces/nlp/test_nlp_tasks.py
+++ b/tests/interfaces/nlp/test_nlp_tasks.py
@@ -13,13 +13,13 @@
 # limitations under the License.
 """Tests for the NLP task definitions"""
 # Standard
-from typing import Dict, Type
+from typing import Dict
 
 # Third Party
 import pytest
 
 # Local
-from caikit.core import ModuleBase, TaskBase, module
+from caikit.core import ModuleBase, module
 from caikit.interfaces.nlp import tasks as nlp_tasks
 from tests.core.helpers import *
 
@@ -42,18 +42,18 @@ class InvalidType:
 )
 def test_tasks(reset_globals, flavor: Dict[str, bool]):
     """Common tests for all tasks"""
-    # Only support single required param named "inputs"
+    # Only support single required param named "text"
     task = nlp_tasks.TextGenerationTask
     assert set(task.get_required_parameters(flavor["input_streaming"]).keys()) == {
-        "inputs"
+        "text"
     }
-    input_type = task.get_required_parameters(flavor["input_streaming"])["inputs"]
+    input_type = task.get_required_parameters(flavor["input_streaming"])["text"]
     output_type = task.get_output_type(flavor["output_streaming"])
 
     # Version with the right signature and nothing else
     @module(id="foo1", name="Foo", version="0.0.0", task=task)
     class Foo1(ModuleBase):
-        def run(self, inputs: input_type) -> output_type:
+        def run(self, text: input_type) -> output_type:
             return output_type()
 
     # Version with the right signature plus extra args
@@ -61,7 +61,7 @@ def test_tasks(reset_globals, flavor: Dict[str, bool]):
     class Foo2(ModuleBase):
         def run(
             self,
-            inputs: input_type,
+            text: input_type,
             workit: bool,
             makeit: bool,
             doit: bool,
@@ -83,7 +83,7 @@ def test_tasks(reset_globals, flavor: Dict[str, bool]):
         @module(id="foo4", name="Foo", version="0.0.0", task=task)
         class Foo4(ModuleBase):
             @task.taskmethod(**flavor)
-            def run(self, inputs: InvalidType) -> output_type:
+            def run(self, text: InvalidType) -> output_type:
                 return output_type()
 
     # Version with bad return type
@@ -92,5 +92,5 @@ def test_tasks(reset_globals, flavor: Dict[str, bool]):
         @module(id="foo", name="Foo", version="0.0.0", task=task)
         class Foo(ModuleBase):
             @task.taskmethod(**flavor)
-            def run(self, inputs: input_type) -> InvalidType:
+            def run(self, text: input_type) -> InvalidType:
                 return "hi there"
diff --git a/tests/interfaces/nlp/test_text_generation.py b/tests/interfaces/nlp/test_text_generation.py
new file mode 100644
index 00000000..8630f0ae
--- /dev/null
+++ b/tests/interfaces/nlp/test_text_generation.py
@@ -0,0 +1,50 @@
+# 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.
+
+# Local
+from caikit.interfaces.nlp.data_model import FinishReason, GeneratedTextResult
+
+## Setup #########################################################################
+
+dummy_generated_response = GeneratedTextResult(
+    generated_text="foo bar", generated_tokens=2, finish_reason=FinishReason.TIME_LIMIT
+)
+
+## Tests ########################################################################
+
+### Generated Text Result
+def test_all_fields_accessible():
+    generated_response = GeneratedTextResult(
+        generated_text="foo bar",
+        generated_tokens=2,
+        finish_reason=FinishReason.STOP_SEQUENCE,
+    )
+    # assert all((hasattr(obj, field) for field in obj.fields))
+    assert generated_response.generated_text == "foo bar"
+    assert generated_response.generated_tokens == 2
+    assert generated_response.finish_reason == FinishReason.STOP_SEQUENCE
+
+
+def test_from_proto_and_back():
+    new = GeneratedTextResult.from_proto(dummy_generated_response.to_proto())
+    assert new.generated_text == "foo bar"
+    assert new.generated_tokens == 2
+    assert new.finish_reason == FinishReason.TIME_LIMIT.value
+
+
+def test_from_json_and_back():
+    new = GeneratedTextResult.from_json(dummy_generated_response.to_json())
+    assert new.generated_text == "foo bar"
+    assert new.generated_tokens == 2
+    assert new.finish_reason == FinishReason.TIME_LIMIT.value