Skip to content

Commit 76ccd4a

Browse files
committed
Add scaffolding for role explanation endpoint
1 parent 64fcf85 commit 76ccd4a

39 files changed

+567
-1
lines changed

README-ANSIBLE_AI_MODEL_MESH_CONFIG.md

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ ANSIBLE_AI_MODEL_MESH_CONFIG="{
3131
"config": {
3232
"inference_url": "http://host.containers.internal:11434",
3333
"model_id": "mistral:instruct"}},
34+
"ModelPipelineRoleExplanation": {
35+
"provider": "ollama",
36+
"config": {
37+
"inference_url": "http://host.containers.internal:11434",
38+
"model_id": "mistral:instruct"}},
3439
"ModelPipelineChatBot": {
3540
"provider": "http",
3641
"config": {

ansible_ai_connect/ai/api/model_pipelines/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Implementations of a pipeline, for a particular provider, for a particular featu
3535
- `ModelPipelinePlaybookGeneration`
3636
- `ModelPipelineRoleGeneration`
3737
- `ModelPipelinePlaybookExplanation`
38+
- `ModelPipelineRoleExplanation`
3839
- `ModelPipelineChatBot`
3940

4041
### Registering pipelines
@@ -74,6 +75,7 @@ REGISTRY = {
7475
ModelPipelinePlaybookGeneration: <Implementing class>
7576
ModelPipelineRoleGeneration: <Implementing class>
7677
ModelPipelinePlaybookExplanation: <Implementing class>
78+
ModelPipelineRoleExplanation: <Implementing class>
7779
ModelPipelineChatBot: <Implementing class>
7880
PipelineConfiguration: <Implementing class>
7981
Serializer: <Implementing class>

ansible_ai_connect/ai/api/model_pipelines/dummy/pipelines.py

+16
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
ModelPipelineCompletions,
3131
ModelPipelinePlaybookExplanation,
3232
ModelPipelinePlaybookGeneration,
33+
ModelPipelineRoleExplanation,
3334
ModelPipelineRoleGeneration,
3435
PlaybookExplanationParameters,
3536
PlaybookExplanationResponse,
3637
PlaybookGenerationParameters,
3738
PlaybookGenerationResponse,
39+
RoleExplanationParameters,
40+
RoleExplanationResponse,
3841
RoleGenerationParameters,
3942
RoleGenerationResponse,
4043
)
@@ -200,3 +203,16 @@ def invoke(self, params: PlaybookExplanationParameters) -> PlaybookExplanationRe
200203

201204
def self_test(self) -> Optional[HealthCheckSummary]:
202205
raise NotImplementedError
206+
207+
208+
@Register(api_type="dummy")
209+
class DummyRoleExplanationPipeline(DummyMetaData, ModelPipelineRoleExplanation[DummyConfiguration]):
210+
211+
def __init__(self, config: DummyConfiguration):
212+
super().__init__(config=config)
213+
214+
def invoke(self, params: RoleExplanationParameters) -> RoleExplanationResponse:
215+
return EXPLANATION
216+
217+
def self_test(self) -> Optional[HealthCheckSummary]:
218+
raise NotImplementedError

ansible_ai_connect/ai/api/model_pipelines/dummy/tests/test_factory.py

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
DummyCompletionsPipeline,
1919
DummyPlaybookExplanationPipeline,
2020
DummyPlaybookGenerationPipeline,
21+
DummyRoleExplanationPipeline,
2122
DummyRoleGenerationPipeline,
2223
)
2324
from ansible_ai_connect.ai.api.model_pipelines.nop.pipelines import (
@@ -30,6 +31,7 @@
3031
ModelPipelineContentMatch,
3132
ModelPipelinePlaybookExplanation,
3233
ModelPipelinePlaybookGeneration,
34+
ModelPipelineRoleExplanation,
3335
ModelPipelineRoleGeneration,
3436
)
3537
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
@@ -62,5 +64,10 @@ def test_playbook_explanation_pipeline(self):
6264
ModelPipelinePlaybookExplanation, DummyPlaybookExplanationPipeline
6365
)
6466

67+
def test_role_explanation_pipeline(self):
68+
self.assert_concrete_implementation(
69+
ModelPipelineRoleExplanation, DummyRoleExplanationPipeline
70+
)
71+
6572
def test_chatbot_pipeline(self):
6673
self.assert_default_implementation(ModelPipelineChatBot, NopChatBotPipeline)

ansible_ai_connect/ai/api/model_pipelines/grpc/tests/test_factory.py

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
NopContentMatchPipeline,
2323
NopPlaybookExplanationPipeline,
2424
NopPlaybookGenerationPipeline,
25+
NopRoleExplanationPipeline,
2526
NopRoleGenerationPipeline,
2627
)
2728
from ansible_ai_connect.ai.api.model_pipelines.pipelines import (
@@ -30,6 +31,7 @@
3031
ModelPipelineContentMatch,
3132
ModelPipelinePlaybookExplanation,
3233
ModelPipelinePlaybookGeneration,
34+
ModelPipelineRoleExplanation,
3335
ModelPipelineRoleGeneration,
3436
)
3537
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
@@ -60,5 +62,8 @@ def test_playbook_explanation_pipeline(self):
6062
ModelPipelinePlaybookExplanation, NopPlaybookExplanationPipeline
6163
)
6264

65+
def test_role_explanation_pipeline(self):
66+
self.assert_default_implementation(ModelPipelineRoleExplanation, NopRoleExplanationPipeline)
67+
6368
def test_chatbot_pipeline(self):
6469
self.assert_default_implementation(ModelPipelineChatBot, NopChatBotPipeline)

ansible_ai_connect/ai/api/model_pipelines/http/tests/test_factory.py

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
NopContentMatchPipeline,
2323
NopPlaybookExplanationPipeline,
2424
NopPlaybookGenerationPipeline,
25+
NopRoleExplanationPipeline,
2526
NopRoleGenerationPipeline,
2627
)
2728
from ansible_ai_connect.ai.api.model_pipelines.pipelines import (
@@ -30,6 +31,7 @@
3031
ModelPipelineContentMatch,
3132
ModelPipelinePlaybookExplanation,
3233
ModelPipelinePlaybookGeneration,
34+
ModelPipelineRoleExplanation,
3335
ModelPipelineRoleGeneration,
3436
)
3537
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
@@ -60,5 +62,8 @@ def test_playbook_explanation_pipeline(self):
6062
ModelPipelinePlaybookExplanation, NopPlaybookExplanationPipeline
6163
)
6264

65+
def test_role_explanation_pipeline(self):
66+
self.assert_default_implementation(ModelPipelineRoleExplanation, NopRoleExplanationPipeline)
67+
6368
def test_chatbot_pipeline(self):
6469
self.assert_concrete_implementation(ModelPipelineChatBot, HttpChatBotPipeline)

ansible_ai_connect/ai/api/model_pipelines/langchain/pipelines.py

+21
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@
4040
ModelPipelineCompletions,
4141
ModelPipelinePlaybookExplanation,
4242
ModelPipelinePlaybookGeneration,
43+
ModelPipelineRoleExplanation,
4344
ModelPipelineRoleGeneration,
4445
PlaybookExplanationParameters,
4546
PlaybookExplanationResponse,
4647
PlaybookGenerationParameters,
4748
PlaybookGenerationResponse,
49+
RoleExplanationParameters,
50+
RoleExplanationResponse,
4851
RoleGenerationParameters,
4952
RoleGenerationResponse,
5053
)
@@ -443,3 +446,21 @@ def self_test(self) -> Optional[HealthCheckSummary]:
443446

444447
def get_chat_model(self, model_id):
445448
raise NotImplementedError
449+
450+
451+
class LangchainRoleExplanationPipeline(
452+
LangchainBase[
453+
LANGCHAIN_PIPELINE_CONFIGURATION, RoleExplanationParameters, RoleExplanationResponse
454+
],
455+
ModelPipelineRoleExplanation[LANGCHAIN_PIPELINE_CONFIGURATION],
456+
Generic[LANGCHAIN_PIPELINE_CONFIGURATION],
457+
):
458+
459+
def __init__(self, config: LANGCHAIN_PIPELINE_CONFIGURATION):
460+
super().__init__(config=config)
461+
462+
def self_test(self) -> Optional[HealthCheckSummary]:
463+
raise NotImplementedError
464+
465+
def invoke(self, params: RoleExplanationParameters) -> RoleExplanationResponse:
466+
raise NotImplementedError

ansible_ai_connect/ai/api/model_pipelines/llamacpp/tests/test_factory.py

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
NopContentMatchPipeline,
2323
NopPlaybookExplanationPipeline,
2424
NopPlaybookGenerationPipeline,
25+
NopRoleExplanationPipeline,
2526
NopRoleGenerationPipeline,
2627
)
2728
from ansible_ai_connect.ai.api.model_pipelines.pipelines import (
@@ -30,6 +31,7 @@
3031
ModelPipelineContentMatch,
3132
ModelPipelinePlaybookExplanation,
3233
ModelPipelinePlaybookGeneration,
34+
ModelPipelineRoleExplanation,
3335
ModelPipelineRoleGeneration,
3436
)
3537
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
@@ -60,5 +62,8 @@ def test_playbook_explanation_pipeline(self):
6062
ModelPipelinePlaybookExplanation, NopPlaybookExplanationPipeline
6163
)
6264

65+
def test_role_explanation_pipeline(self):
66+
self.assert_default_implementation(ModelPipelineRoleExplanation, NopRoleExplanationPipeline)
67+
6368
def test_chatbot_pipeline(self):
6469
self.assert_default_implementation(ModelPipelineChatBot, NopChatBotPipeline)

ansible_ai_connect/ai/api/model_pipelines/nop/pipelines.py

+16
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
ModelPipelineContentMatch,
2828
ModelPipelinePlaybookExplanation,
2929
ModelPipelinePlaybookGeneration,
30+
ModelPipelineRoleExplanation,
3031
ModelPipelineRoleGeneration,
3132
PlaybookExplanationParameters,
3233
PlaybookExplanationResponse,
3334
PlaybookGenerationParameters,
3435
PlaybookGenerationResponse,
36+
RoleExplanationParameters,
37+
RoleExplanationResponse,
3538
RoleGenerationParameters,
3639
RoleGenerationResponse,
3740
)
@@ -116,6 +119,19 @@ def self_test(self) -> Optional[HealthCheckSummary]:
116119
raise NotImplementedError
117120

118121

122+
@Register(api_type="nop")
123+
class NopRoleExplanationPipeline(NopMetaData, ModelPipelineRoleExplanation[NopConfiguration]):
124+
125+
def __init__(self, config: NopConfiguration):
126+
super().__init__(config=config)
127+
128+
def invoke(self, params: RoleExplanationParameters) -> RoleExplanationResponse:
129+
raise NotImplementedError
130+
131+
def self_test(self) -> Optional[HealthCheckSummary]:
132+
raise NotImplementedError
133+
134+
119135
@Register(api_type="nop")
120136
class NopChatBotPipeline(NopMetaData, ModelPipelineChatBot[NopConfiguration]):
121137

ansible_ai_connect/ai/api/model_pipelines/ollama/pipelines.py

+14
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
LangchainMetaData,
2222
LangchainPlaybookExplanationPipeline,
2323
LangchainPlaybookGenerationPipeline,
24+
LangchainRoleExplanationPipeline,
2425
LangchainRoleGenerationPipeline,
2526
)
2627
from ansible_ai_connect.ai.api.model_pipelines.ollama.configuration import (
@@ -80,6 +81,19 @@ def get_chat_model(self, model_id):
8081
)
8182

8283

84+
@Register(api_type="ollama")
85+
class OllamaRoleExplanationPipeline(LangchainRoleExplanationPipeline[OllamaConfiguration]):
86+
87+
def __init__(self, config: OllamaConfiguration):
88+
super().__init__(config=config)
89+
90+
def get_chat_model(self, model_id):
91+
return OllamaLLM(
92+
base_url=self.config.inference_url,
93+
model=model_id,
94+
)
95+
96+
8397
@Register(api_type="ollama")
8498
class OllamaPlaybookExplanationPipeline(LangchainPlaybookExplanationPipeline[OllamaConfiguration]):
8599

ansible_ai_connect/ai/api/model_pipelines/ollama/tests/test_factory.py

+7
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
OllamaCompletionsPipeline,
2323
OllamaPlaybookExplanationPipeline,
2424
OllamaPlaybookGenerationPipeline,
25+
OllamaRoleExplanationPipeline,
2526
)
2627
from ansible_ai_connect.ai.api.model_pipelines.pipelines import (
2728
ModelPipelineChatBot,
2829
ModelPipelineCompletions,
2930
ModelPipelineContentMatch,
3031
ModelPipelinePlaybookExplanation,
3132
ModelPipelinePlaybookGeneration,
33+
ModelPipelineRoleExplanation,
3234
)
3335
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
3436
from ansible_ai_connect.ai.api.model_pipelines.tests.test_factory import (
@@ -55,5 +57,10 @@ def test_playbook_explanation_pipeline(self):
5557
ModelPipelinePlaybookExplanation, OllamaPlaybookExplanationPipeline
5658
)
5759

60+
def test_role_explanation_pipeline(self):
61+
self.assert_concrete_implementation(
62+
ModelPipelineRoleExplanation, OllamaRoleExplanationPipeline
63+
)
64+
5865
def test_chatbot_pipeline(self):
5966
self.assert_default_implementation(ModelPipelineChatBot, NopChatBotPipeline)

ansible_ai_connect/ai/api/model_pipelines/pipelines.py

+43
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,35 @@ def init(
184184
PlaybookExplanationResponse = str
185185

186186

187+
@define
188+
class RoleExplanationParameters:
189+
request: Request
190+
files: list
191+
role_name: str
192+
model_id: str
193+
focus_on_file: str
194+
195+
@classmethod
196+
def init(
197+
cls,
198+
request,
199+
files: list = [],
200+
role_name: str = "",
201+
model_id: str = "",
202+
focus_on_file: str = "",
203+
):
204+
return cls(
205+
request=request,
206+
files=files,
207+
role_name=role_name,
208+
model_id=model_id,
209+
focus_on_file=focus_on_file,
210+
)
211+
212+
213+
RoleExplanationResponse = str
214+
215+
187216
@define
188217
class ChatBotParameters:
189218
query: str
@@ -326,6 +355,20 @@ def alias():
326355
return "playbook-explanation"
327356

328357

358+
class ModelPipelineRoleExplanation(
359+
ModelPipeline[PIPELINE_CONFIGURATION, RoleExplanationParameters, RoleExplanationResponse],
360+
Generic[PIPELINE_CONFIGURATION],
361+
metaclass=ABCMeta,
362+
):
363+
364+
def __init__(self, config: PIPELINE_CONFIGURATION):
365+
super().__init__(config=config)
366+
367+
@staticmethod
368+
def alias():
369+
return "role-explanation"
370+
371+
329372
class ModelPipelineChatBot(
330373
ModelPipeline[PIPELINE_CONFIGURATION, ChatBotParameters, ChatBotResponse],
331374
Generic[PIPELINE_CONFIGURATION],

ansible_ai_connect/ai/api/model_pipelines/registry.py

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
ModelPipelineContentMatch,
2929
ModelPipelinePlaybookExplanation,
3030
ModelPipelinePlaybookGeneration,
31+
ModelPipelineRoleExplanation,
3132
ModelPipelineRoleGeneration,
3233
)
3334
from ansible_ai_connect.main.settings.types import t_model_mesh_api_type
@@ -42,6 +43,7 @@
4243
ModelPipelinePlaybookGeneration,
4344
ModelPipelineRoleGeneration,
4445
ModelPipelinePlaybookExplanation,
46+
ModelPipelineRoleExplanation,
4547
ModelPipelineChatBot,
4648
PipelineConfiguration,
4749
Serializer,

ansible_ai_connect/ai/api/model_pipelines/tests/test_factory.py

+16
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
NopContentMatchPipeline,
2222
NopPlaybookExplanationPipeline,
2323
NopPlaybookGenerationPipeline,
24+
NopRoleExplanationPipeline,
2425
)
2526
from ansible_ai_connect.ai.api.model_pipelines.pipelines import (
2627
PIPELINE_TYPE,
2728
MetaData,
2829
ModelPipelineContentMatch,
2930
ModelPipelinePlaybookExplanation,
3031
ModelPipelinePlaybookGeneration,
32+
ModelPipelineRoleExplanation,
3133
)
3234
from ansible_ai_connect.ai.api.model_pipelines.tests import mock_config
3335
from ansible_ai_connect.test_utils import WisdomServiceAPITestCaseBaseOIDC
@@ -91,6 +93,20 @@ def test_default_fallback_playbook_explanation(self):
9193
log,
9294
)
9395

96+
# 'grpc' does not have a Role Explanation pipeline
97+
@override_settings(ANSIBLE_AI_MODEL_MESH_CONFIG=mock_config("grpc"))
98+
def test_default_fallback_role_explanation(self):
99+
factory = ModelPipelineFactory()
100+
101+
with self.assertLogs(logger="root", level="INFO") as log:
102+
pipeline = factory.get_pipeline(ModelPipelineRoleExplanation)
103+
self.assertIsNotNone(pipeline)
104+
self.assertIsInstance(pipeline, NopRoleExplanationPipeline)
105+
self.assertInLog(
106+
"Using NOP implementation for 'ModelPipelineRoleExplanation'.",
107+
log,
108+
)
109+
94110

95111
class TestModelPipelineFactoryImplementations(WisdomServiceAPITestCaseBaseOIDC):
96112
def assert_concrete_implementation(self, pipeline_type: Type[PIPELINE_TYPE], expected_cls):

0 commit comments

Comments
 (0)