Added the optional Ollama profile advisor
This commit is contained in:
@@ -82,3 +82,43 @@ def ollama_dashboard_assessment(analysis: dict[str, object], model: str | None =
|
||||
},
|
||||
timeout=timeout,
|
||||
)
|
||||
|
||||
|
||||
def ollama_profile_advice(suggestions: list[dict[str, object]], model: str | None = None, timeout: int | None = None) -> list[dict[str, object]]:
|
||||
host = os.getenv("OLLAMA_HOST", "http://127.0.0.1:11434").rstrip("/")
|
||||
selected_model = model or os.getenv("FGAI_PROFILE_ADVISOR_MODEL", "qwen3:8b")
|
||||
selected_timeout = timeout or int(os.getenv("FGAI_PROFILE_ADVISOR_TIMEOUT", "120"))
|
||||
compact = [
|
||||
{
|
||||
"stream_id": item.get("stream_id"),
|
||||
"stream_name": item.get("stream_name"),
|
||||
"events": item.get("events"),
|
||||
"common_fields": item.get("common_fields", [])[:20],
|
||||
"heuristic_profile": item.get("profile", {}),
|
||||
}
|
||||
for item in suggestions[:10]
|
||||
]
|
||||
body = json.dumps(
|
||||
{
|
||||
"model": selected_model,
|
||||
"stream": False,
|
||||
"format": "json",
|
||||
"options": {"num_predict": 1200, "temperature": 0.1},
|
||||
"prompt": (
|
||||
"You are SignalScope's local profile advisor. Infer stream profile mappings from observed field statistics. "
|
||||
"Return only valid JSON with this schema: "
|
||||
"{\"profiles\":[{\"stream_id\":\"...\",\"entity_fields\":[\"...\"],\"timestamp_field\":\"...\","
|
||||
"\"categorical_fields\":[\"...\"],\"numeric_fields\":[\"...\"],\"detectors\":{\"auth_failure\":{\"enabled\":true,\"minimum\":5,\"z_threshold\":3}},"
|
||||
"\"reason\":\"short reason\"}]}. "
|
||||
"Use only field names present in common_fields or heuristic_profile. Do not include raw message/full_message fields. "
|
||||
"Allowed detectors are auth_failure, dns_query, deny_action. Prefer canonical fields such as username, hostname, eventid, srcip, dstip when present. "
|
||||
f"\n\nObserved streams:\n{json.dumps(compact, sort_keys=True)}"
|
||||
),
|
||||
}
|
||||
).encode("utf-8")
|
||||
req = request.Request(f"{host}/api/generate", data=body, method="POST", headers={"Content-Type": "application/json"})
|
||||
with request.urlopen(req, timeout=selected_timeout) as response:
|
||||
data = json.loads(response.read().decode("utf-8"))
|
||||
payload = json.loads(str(data.get("response", "{}")))
|
||||
profiles = payload.get("profiles", [])
|
||||
return profiles if isinstance(profiles, list) else []
|
||||
|
||||
Reference in New Issue
Block a user