Skip to content

Commit

Permalink
WCA: add playbook explanation and generation end-points
Browse files Browse the repository at this point in the history
- Add the new endpoints
- Add a `request` parameter to `generate_playbook()` and `explain_playbook()`. We need
  it to get the user `organization_id`.
  • Loading branch information
goneri committed May 28, 2024
1 parent b858d5e commit e2d8e12
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 15 deletions.
4 changes: 2 additions & 2 deletions ansible_wisdom/ai/api/model_client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ def get_chat_model(self, model_id):
raise NotImplementedError

def generate_playbook(
self, text: str = "", create_outline: bool = False, outline: str = ""
self, request, text: str = "", create_outline: bool = False, outline: str = ""
) -> tuple[str, str]:
raise NotImplementedError

def explain_playbook(self, content) -> str:
def explain_playbook(self, request, content) -> str:
raise NotImplementedError

def self_test(self) -> HealthCheckSummary:
Expand Down
4 changes: 2 additions & 2 deletions ansible_wisdom/ai/api/model_client/dummy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ def infer(self, model_input, model_id="", suggestion_id=None) -> Dict[str, Any]:
return response_body

def generate_playbook(
self, text: str = "", create_outline: bool = False, outline: str = ""
self, request, text: str = "", create_outline: bool = False, outline: str = ""
) -> tuple[str, str]:
if create_outline:
return PLAYBOOK, OUTLINE
return PLAYBOOK, ""

def explain_playbook(self, content) -> str:
def explain_playbook(self, request, content) -> str:
return EXPLANATION
4 changes: 2 additions & 2 deletions ansible_wisdom/ai/api/model_client/langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def infer(self, model_input, model_id="", suggestion_id=None) -> Dict[str, Any]:
raise ModelTimeoutError

def generate_playbook(
self, text: str = "", create_outline: bool = False, outline: str = ""
self, request, text: str = "", create_outline: bool = False, outline: str = ""
) -> tuple[str, str]:
SYSTEM_MESSAGE_TEMPLATE = """
You are an Ansible expert.
Expand Down Expand Up @@ -178,7 +178,7 @@ def generate_playbook(

return playbook, outline

def explain_playbook(self, content) -> str:
def explain_playbook(self, request, content) -> str:
SYSTEM_MESSAGE_TEMPLATE = """
You're an Ansible expert.
You format your output with Markdown.
Expand Down
6 changes: 3 additions & 3 deletions ansible_wisdom/ai/api/model_client/tests/test_dummy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,20 @@ def test_infer_without_jitter(self, loads, sleep):

def test_generate_playbook(self):
client = DummyClient(inference_url="https://ibm.com")
playbook, outline = client.generate_playbook(text="foo", create_outline=False)
playbook, outline = client.generate_playbook(None, text="foo", create_outline=False)
self.assertTrue(isinstance(playbook, str))
self.assertTrue(isinstance(outline, str))
self.assertEqual(outline, "")

def test_generate_playbook_with_outline(self):
client = DummyClient(inference_url="https://ibm.com")
playbook, outline = client.generate_playbook(text="foo", create_outline=True)
playbook, outline = client.generate_playbook(None, text="foo", create_outline=True)
self.assertTrue(isinstance(playbook, str))
self.assertTrue(isinstance(outline, str))
self.assertTrue(outline)

def test_explain_playbook(self):
client = DummyClient(inference_url="https://ibm.com")
explanation = client.explain_playbook("ëoo")
explanation = client.explain_playbook(None, "ëoo")
self.assertTrue(isinstance(explanation, str))
self.assertTrue(explanation)
5 changes: 3 additions & 2 deletions ansible_wisdom/ai/api/model_client/tests/test_langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,17 @@ def fake_get_chat_mode(self, model_id=None):

def test_generate_playbook(self):
playbook, outline = self.my_client.generate_playbook(
None,
text="foo",
)
self.assertEqual(playbook, "my_playbook")
self.assertEqual(outline, "")

def test_generate_playbook_with_outline(self):
playbook, outline = self.my_client.generate_playbook(text="foo", create_outline=True)
playbook, outline = self.my_client.generate_playbook(None, text="foo", create_outline=True)
self.assertEqual(playbook, "my_playbook")
self.assertEqual(outline, "my outline")

def test_explain_playbook(self):
explanation = self.my_client.explain_playbook(content="foo")
explanation = self.my_client.explain_playbook(None, content="foo")
self.assertTrue(explanation)
4 changes: 2 additions & 2 deletions ansible_wisdom/ai/api/model_client/tests/test_model_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ def test_not_implemented(self):
with self.assertRaises(NotImplementedError):
c.get_chat_model("a")
with self.assertRaises(NotImplementedError):
c.generate_playbook("a")
c.generate_playbook(None, "a")
with self.assertRaises(NotImplementedError):
c.explain_playbook("a")
c.explain_playbook(None, "a")
29 changes: 29 additions & 0 deletions ansible_wisdom/ai/api/model_client/tests/test_wca_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,35 @@ def test_fatal_exception(self):
b = WCAClient.fatal_exception(exc)
self.assertTrue(b)

def test_playbook_gen(self):
wca_client = WCAClient(inference_url='http://example.com/')
wca_client.get_api_key = Mock(return_value="some-key")
wca_client.get_token = Mock(return_value={"access_token": "a-token"})
wca_client.get_model_id = Mock(return_value="a-random-model")
wca_client.session = Mock()
response = Mock
response.text = '{"playbook": "Oh!", "outline": "Ahh!"}'
wca_client.session.post.return_value = response
request = Mock()
playbook, outline = wca_client.generate_playbook(
request, text="Install Wordpress", create_outline=True
)
self.assertEqual(playbook, "Oh!")
self.assertEqual(outline, "Ahh!")

def test_playbook_exp(self):
wca_client = WCAClient(inference_url='http://example.com/')
wca_client.get_api_key = Mock(return_value="some-key")
wca_client.get_token = Mock(return_value={"access_token": "a-token"})
wca_client.get_model_id = Mock(return_value="a-random-model")
wca_client.session = Mock()
response = Mock
response.text = '{"explanation": "!Óh¡"}'
wca_client.session.post.return_value = response
request = Mock()
explanation = wca_client.explain_playbook(request, content="Some playbook")
self.assertEqual(explanation, "!Óh¡")


@override_settings(ANSIBLE_WCA_RETRY_COUNT=1)
@override_settings(WCA_SECRET_BACKEND_TYPE="dummy")
Expand Down
39 changes: 39 additions & 0 deletions ansible_wisdom/ai/api/model_client/wca_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,45 @@ def self_test(self) -> HealthCheckSummary:

return summary

def generate_playbook(
self, request, text: str = "", create_outline: bool = False, outline: str = ""
) -> tuple[str, str]:
api_key = self.get_api_key(request.user.organization.id)
model_id = self.get_model_id(request.user.organization.id)

headers = self._get_base_headers(api_key)
data = {
"model_id": model_id,
"text": text,
"create_outline": create_outline,
}
if outline:
data["outline"] = outline
result = self.session.post(
f"{self._inference_url}/v1/wca/codegen/ansible/playbook",
headers=headers,
json=data,
)
response = json.loads(result.text)
return response["playbook"], response["outline"]

def explain_playbook(self, request, content: str) -> str:
api_key = self.get_api_key(request.user.organization.id)
model_id = self.get_model_id(request.user.organization.id)

headers = self._get_base_headers(api_key)
data = {
"model_id": model_id,
"playbook": content,
}
result = self.session.post(
f"{self._inference_url}/v1/wca/explain/ansible/playbook",
headers=headers,
json=data,
)
response = json.loads(result.text)
return response["explanation"]


class WCAOnPremClient(BaseWCAClient):
def __init__(self, inference_url):
Expand Down
4 changes: 2 additions & 2 deletions ansible_wisdom/ai/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ def post(self, request) -> Response:
playbook = request_serializer.validated_data.get("content")

llm = apps.get_app_config("ai").model_mesh_client
explanation = llm.explain_playbook(playbook)
explanation = llm.explain_playbook(request, playbook)

answer = {"content": explanation, "format": "markdown", "explanationId": explanation_id}

Expand Down Expand Up @@ -789,7 +789,7 @@ def post(self, request) -> Response:
text = request_serializer.validated_data["text"]

llm = apps.get_app_config("ai").model_mesh_client
playbook, outline = llm.generate_playbook(text, create_outline, outline)
playbook, outline = llm.generate_playbook(request, text, create_outline, outline)

answer = {
"playbook": playbook,
Expand Down

1 comment on commit e2d8e12

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClamAV Virus Definition DB Files:
----
total 228988
-rw-r--r--  1 root root        28 May 28 06:07 whitelist.ign2
-rw-r--r--  1 root root 170479789 May 28 06:08 main.cvd
-rw-r--r--  1 root root        69 May 28 06:07 freshclam.dat
-rw-r--r--  1 root root  63685486 May 28 06:07 daily.cvd
-rw-r--r--  1 root root    289733 May 28 06:08 bytecode.cvd
drwxr-xr-x 16 root root      4096 May 28 14:08 ..
drwxr-xr-x  2 root root      4096 May 28 14:08 .
----
File: /var/lib/clamav/bytecode.cvd
Build time: 27 Feb 2024 10:37 -0500
Version: 335
Signatures: 86
Functionality level: 90
Builder: raynman
MD5: 16d388f042f5c44628a66228df427c20
Digital signature: 7fD3mweaw4tqQH9Dl7ZewBLXZBSrLKX5no/rYN/6NQBmhnWUyTBt3uzd7ZjEnIT5yN1ygLwsDcuzoKRoA+syrfk3PcDHf5/h6Wb/d8uikXSALygH5VYAPo2ksV5Pitn3reECJ90q2m9m0CH2VpT1tDkkcVi05LLV5PwBle2Ufpe
Verification OK.
----
File: /var/lib/clamav/daily.cvd
Build time: 27 May 2024 04:29 -0400
Version: 27288
Signatures: 2061829
Functionality level: 90
Builder: raynman
MD5: 9eac0d4a0279d4a14dc57108e6b1d78a
Digital signature: oaQevAiBsZTVuBp7fu9o7lR/xkJIb0y3m6O1pM7k9cvR4RFJ7vb6m8pFYqY+leMyoXVFjmz+QU6hTZhoKkqjBfSYmDFp0gYUQVC8rq99qzMFWC6qX5E7igOTikIGpGhno8vgvKqEqh6w0pPV8B8KD8TElgKJd+IeGB+UwUP9Jrf
Verification OK.
----
File: /var/lib/clamav/main.cvd
Build time: 16 Sep 2021 08:32 -0400
Version: 62
Signatures: 6647427
Functionality level: 90
Builder: sigmgr
MD5: 137eccce31aacb21b5a98bb8c21cefd6
Digital signature: twaJBls8V5q64R7QY10AatEtPNuPWoVoxTaNO1jpBg7s5jIMMXpitgG1000YLp6rb0TWkEKjRqxneGTxuxWaWm7XBjsgwX2BRWh/y4fhs7uyImdKRLzQ5y8e2EkSChegF/i8clqfn+1qetq9j4gbktJ3JZpOXPoHlyr2Dv9S/Bg
Verification OK.
----
Scanning Results:
ClamAV 1.0.6/27288/Mon May 27 08:29:01 2024
LibClamAV Warning: Max file-size was set to 4194304000 bytes. Unfortunately, scanning files greater than 2147483647 bytes (2 GiB - 1) is not supported.

----------- SCAN SUMMARY -----------
Known viruses: 8693656
Engine version: 1.0.6
Scanned directories: 31514
Scanned files: 194737
Infected files: 0
Data scanned: 6712.74 MB
Data read: 3521.66 MB (ratio 1.91:1)
Time: 1436.107 sec (23 m 56 s)
Start Date: 2024:05:28 14:10:24
End Date:   2024:05:28 14:34:20

Please sign in to comment.