Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAIN-2806: add structured sections to AI output #1698

Merged
merged 6 commits into from
Jan 28, 2025
Merged
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
2 changes: 2 additions & 0 deletions src/robusta/core/model/base_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class AIInvestigateParams(HolmesParams):
:var runbooks: List of human readable recommended runbooks that holmes can use for the investigation.
:var ask: Override question to ask holmes
:var context: Additional information that can assist with the investigation
:var sections: Sections that Holmes should return. Dictionary where the key is the section's title and the value a description for Holmes (LLM)

:example ask: What are all the issues in my cluster right now?
:example runbooks: ["Try to get the pod logs and find errors", "get the pod yaml and check if there are finalizers"]
Expand All @@ -109,6 +110,7 @@ class AIInvestigateParams(HolmesParams):
runbooks: Optional[List[str]]
ask: Optional[str]
context: Optional[Dict[str, Any]]
sections: Optional[Dict[str, str]] = None


class HolmesToolsResult(BaseModel):
Expand Down
3 changes: 2 additions & 1 deletion src/robusta/core/playbooks/internal/ai_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def ask_holmes(event: ExecutionBaseEvent, params: AIInvestigateParams):
context=params.context if params.context else {},
include_tool_calls=True,
include_tool_call_results=True,
sections=params.sections
)
result = requests.post(f"{holmes_url}/api/investigate", data=holmes_req.json())
result.raise_for_status()
Expand Down Expand Up @@ -123,7 +124,7 @@ def holmes_workload_health(event: ExecutionBaseEvent, params: HolmesWorkloadHeal
analysis = json.loads(holmes_result.analysis)
healthy = analysis.get("workload_healthy")
except Exception:
logging.exception("Error in holmes response format, analysis did not return the expecrted json format.")
logging.exception("Error in holmes response format, analysis did not return the expected json format.")
pass

if params.silent_healthy and healthy:
Expand Down
4 changes: 3 additions & 1 deletion src/robusta/core/reporting/holmes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel

Expand All @@ -19,6 +19,7 @@ class HolmesRequest(BaseModel):
context: Dict[str, Any]
include_tool_calls: bool = False
include_tool_call_results: bool = False
sections: Optional[Dict[str, str]] = None


class HolmesConversationRequest(BaseModel):
Expand Down Expand Up @@ -50,6 +51,7 @@ class ToolCallResult(BaseModel):
class HolmesResult(BaseModel):
tool_calls: Optional[List[ToolCallResult]] = None
analysis: Optional[str] = None
sections: Optional[Dict[str, Union[str, None]]] = None
instructions: List[str] = []


Expand Down
16 changes: 16 additions & 0 deletions src/robusta/core/sinks/robusta/dal/model_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def append_to_structured_data_tool_calls(tool_calls: List[ToolCallResult], struc
data_obj["metadata"] = {"description": tool_call.description, "tool_name": tool_call.tool_name}
structured_data.append(data_obj)


@staticmethod
def add_ai_chat_data(structured_data: List[Dict], block: HolmesChatResultsBlock):
structured_data.append(
Expand All @@ -117,6 +118,8 @@ def add_ai_chat_data(structured_data: List[Dict], block: HolmesChatResultsBlock)

@staticmethod
def add_ai_analysis_data(structured_data: List[Dict], block: HolmesResultsBlock):
if not block.holmes_result:
return
structured_data.append(
{
"type": "markdown",
Expand All @@ -125,6 +128,19 @@ def add_ai_analysis_data(structured_data: List[Dict], block: HolmesResultsBlock)
}
)
ModelConversion.append_to_structured_data_tool_calls(block.holmes_result.tool_calls, structured_data)
if block.holmes_result.sections and len(block.holmes_result.sections) > 0:
transformed_sections = {}
for section_title, section_content in block.holmes_result.sections.items():
if section_content:
transformed_sections[section_title] = Transformer.to_github_markdown(section_content)

structured_data.append(
{
"type": "markdown",
"metadata": {"type": "ai_investigation_sections", "createdAt": datetime_to_db_str(datetime.now())},
"data": transformed_sections,
}
)

structured_data.append({"type": "list", "data": block.holmes_result.instructions})

Expand Down
Loading