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

feat: Setup assistant agent & workflow file. #1002

Merged
merged 11 commits into from
Jan 23, 2024
29 changes: 29 additions & 0 deletions .github/workflows/assistant-release-e2e-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Assistant Release tests workflow in Bundled OpenSearch Dashboards
on:
pull_request:
branches: ['**']
env:
CYPRESS_ASSISTANT_AGENT_INITIALIZE_REQUIRED: true
CYPRESS_AWS_ACCOUNT_ACCESS_KEY: ${{ secrets.CYPRESS_AWS_ACCOUNT_ACCESS_KEY }}
CYPRESS_AWS_ACCOUNT_SECRET_KEY: ${{ secrets.CYPRESS_AWS_ACCOUNT_SECRET_KEY }}
jobs:
changes:
runs-on: ubuntu-latest
outputs:
tests: ${{ steps.filter.outputs.tests }}
steps:
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
tests:
- 'cypress/**/dashboards-assistant/**'

tests:
needs: changes
if: ${{ needs.changes.outputs.tests == 'true' }}
uses: ./.github/workflows/release-e2e-workflow-template.yml
with:
test-name: dashboards assistant
test-command: yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/*'
osd-serve-args: --assistant.chat.enabled=true --assistant.chat.rootAgentName="Cypress test agent"
172 changes: 172 additions & 0 deletions cypress/fixtures/plugins/dashboards-assistant/flow-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{
"name": "Cypress-register-agent",
"description": "Cypress Flow template",
"use_case": "REGISTER_AGENT",
"version": {
"template": "1.0.0",
"compatibility": ["2.12.0", "3.0.0"]
},
"workflows": {
"provision": {
"user_params": {},
"nodes": [
{
"id": "create_connector_1",
"type": "create_connector",
"previous_node_inputs": {},
"user_inputs": {
"version": "1",
"name": "Claude instant runtime Connector",
"protocol": "aws_sigv4",
"description": "The connector to BedRock service for claude model",
"actions": [
{
"headers": {
"x-amz-content-sha256": "required",
"content-type": "application/json"
},
"method": "POST",
"request_body": "{\"prompt\":\"${parameters.prompt}\", \"max_tokens_to_sample\":${parameters.max_tokens_to_sample}, \"temperature\":${parameters.temperature}, \"anthropic_version\":\"${parameters.anthropic_version}\" }",
"action_type": "predict",
"url": "https://bedrock-runtime.us-west-2.amazonaws.com/model/anthropic.claude-instant-v1/invoke"
}
],
"credential": {
"access_key": "${CYPRESS_AWS_ACCOUNT_ACCESS_KEY}",
"secret_key": "${CYPRESS_AWS_ACCOUNT_SECRET_KEY}"
},
"parameters": {
"endpoint": "bedrock-runtime.us-west-2.amazonaws.com",
"content_type": "application/json",
"auth": "Sig_V4",
"max_tokens_to_sample": "8000",
"service_name": "bedrock",
"temperature": "0.0001",
"response_filter": "$.completion",
"region": "us-west-2",
"anthropic_version": "bedrock-2023-05-31"
}
}
},
{
"id": "register_model_2",
"type": "register_remote_model",
"previous_node_inputs": {
"create_connector_1": "connector_id"
},
"user_inputs": {
"description": "test model",
"deploy": true,
"name": "claude-instant"
}
},
{
"id": "cat_index_tool",
"type": "create_tool",
"previous_node_inputs": {},
"user_inputs": {
"type": "CatIndexTool",
"name": "CatIndexTool",
"description": "Use this tool to get OpenSearch index information: (health, status, index, uuid, primary count, replica count, docs.count, docs.deleted, store.size, primary.store.size).",
"parameters": {
"index": ".kibana"
}
}
},
{
"id": "visualization_tool",
"type": "create_tool",
"previous_node_inputs": {},
"user_inputs": {
"description": "Use this tool to find user created visualizations. This tool takes the visualization name as input and returns the first 3 matching visualizations",
"include_output_in_agent_response": true,
"type": "VisualizationTool",
"parameters": {
"index": ".kibana"
},
"name": "VisualizationTool"
}
},
{
"id": "sub_agent",
"type": "register_agent",
"previous_node_inputs": {
"cat_index_tool": "tools",
"register_model_2": "model_id",
"visualization_tool": "tools"
},
"user_inputs": {
"parameters": {},
"app_type": "chatbot",
"name": "Cypress test sub Agent",
"description": "this is a test agent",
"llm.parameters": {
"max_iteration": "5",
"stop_when_no_tool_found": "true",
"response_filter": "$.completion"
},
"memory": {
"type": "conversation_index"
},
"type": "conversational"
}
},
{
"id": "agent_tool",
"type": "create_tool",
"previous_node_inputs": {
"sub_agent": "agent_id"
},
"user_inputs": {
"description": "Agent Tool",
"include_output_in_agent_response": true,
"type": "AgentTool",
"parameters": {
"max_iteration": "5"
},
"name": "AgentTool"
}
},
{
"id": "ml_model_tool",
"type": "create_tool",
"previous_node_inputs": {
"register_model_2": "model_id"
},
"user_inputs": {
"parameters": {
"prompt": "\n\nHuman:\" turn\" You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]}\n\n. \n\nHuman:\" turn\":You will be given a chat history between OpenSearch Assistant and a Human.\nUse the context provided to generate follow up questions the Human would ask to the Assistant.\nThe Assistant can answer general questions about logs, traces and metrics.\nAssistant can access a set of tools listed below to answer questions given by the Human:\nQuestion suggestions generator tool\nHere's the chat history between the human and the Assistant.\n${parameters.AgentTool.output}\nUse the following steps to generate follow up questions Human may ask after the response of the Assistant:\nStep 1. Use the chat history to understand what human is trying to search and explore.\nStep 2. Understand what capabilities the assistant has with the set of tools it has access to.\nStep 3. Use the above context and generate follow up questions.Step4:You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]} \n \n----------------\n\nAssistant:"
},
"description": "A general tool to answer any question.",
"alias": "language_model_tool",
"include_output_in_agent_response": true,
"name": "QuestionSuggestor",
"type": "MLModelTool"
}
},
{
"id": "root_agent",
"type": "register_agent",
"previous_node_inputs": {
"agent_tool": "tools",
"register_model_2": "model_id",
"ml_model_tool": "tools"
},
"user_inputs": {
"parameters": {
"prompt": "Answer the question as best you can."
},
"app_type": "chatbot",
"name": "Cypress test agent",
"description": "this is the root agent",
"tools_order": ["agent_tool", "ml_model_tool"],
"memory": {
"type": "conversation_index"
},
"type": "flow"
}
}
]
}
}
}
27 changes: 27 additions & 0 deletions cypress/integration/plugins/dashboards-assistant/basic_spec.js
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the dashboards-assistant plugin was experimental by default, shall we add a flag to disabled the functional tests by default?

Copy link
Member Author

Choose a reason for hiding this comment

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

I am not sure about this part, I thought experimental means it should be controlled behind a feature flag. For integration test, no matter experimental or not, they all should be triggered if test cases changed.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { BASE_PATH } from '../../../utils/constants';

describe('Assistant basic spec', () => {
before(() => {
// Set welcome screen tracking to false
localStorage.setItem('home:welcome:show', 'false');
});

beforeEach(() => {
// Visit ISM OSD
cy.visit(`${BASE_PATH}/app/home`);

// Common text to wait for to confirm page loaded, give up to 60 seconds for initial load
cy.get(`input[placeholder="Ask question"]`, { timeout: 60000 }).should(
'be.length',
1
);
});

describe('show up', () => {
it.only('successfully', () => {});
});
});
8 changes: 8 additions & 0 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import '../utils/plugins/alerting-dashboards-plugin/commands';
import '../utils/plugins/ml-commons-dashboards/commands';
import '../utils/plugins/security-analytics-dashboards-plugin/commands';
import '../utils/plugins/notifications-dashboards/commands';
import '../utils/plugins/dashboards-assistant/commands';

import 'cypress-real-events';

Expand All @@ -56,3 +57,10 @@ if (Cypress.env('ENDPOINT_WITH_PROXY')) {
Cypress.Cookies.preserveOnce('security_authentication');
});
}

if (Cypress.env('CYPRESS_ASSISTANT_AGENT_INITIALIZE_REQUIRED')) {
before(() => {
cy.addAssistantRequiredSettings();
cy.registerRootAgent();
});
}
56 changes: 56 additions & 0 deletions cypress/utils/plugins/dashboards-assistant/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import FlowTemplateJSON from '../../../fixtures/plugins/dashboards-assistant/flow-template.json';
import { BACKEND_BASE_PATH } from '../../constants';
import { FLOW_FRAMEWORK_API } from './constants';

Cypress.Commands.add('addAssistantRequiredSettings', () => {
cy.request('PUT', `${BACKEND_BASE_PATH}/_cluster/settings`, {
persistent: {
'plugins.ml_commons.only_run_on_ml_node': false,
'plugins.ml_commons.memory_feature_enabled': true,
'plugins.flow_framework.enabled': true,
'plugins.ml_commons.trusted_connector_endpoints_regex': [
'^https://bedrock-runtime\\.us-west-2\\.amazonaws\\.com/.*$',
],
},
});
});

Cypress.Commands.add('registerRootAgent', () => {
cy.request(
'POST',
`${BACKEND_BASE_PATH}${FLOW_FRAMEWORK_API.CREATE_FLOW_TEMPLATE}`,
JSON.parse(
JSON.stringify(FlowTemplateJSON)
.replace(
'${CYPRESS_AWS_ACCOUNT_ACCESS_KEY}',
Cypress.env('CYPRESS_AWS_ACCOUNT_ACCESS_KEY') || ''
)
.replace(
'${CYPRESS_AWS_ACCOUNT_SECRET_KEY}',
Cypress.env('CYPRESS_AWS_ACCOUNT_SECRET_KEY') || ''
)
)
).then((resp) => {
// ML needs 10 seconds to initialize its master key
// The ML encryption master key has not been initialized yet. Please retry after waiting for 10 seconds.
cy.wait(10000);
const workflowId = resp.body.workflow_id;
if (workflowId) {
cy.request(
'POST',
`${BACKEND_BASE_PATH}${FLOW_FRAMEWORK_API.CREATE_FLOW_TEMPLATE}/${workflowId}/_provision`
);
/**
* wait for 2s
*/
cy.wait(2000);
} else {
throw new Error(resp);
}
});
});
10 changes: 10 additions & 0 deletions cypress/utils/plugins/dashboards-assistant/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const WORKFLOW_API_PREFIX = '/_plugins/_flow_framework/workflow';

export const FLOW_FRAMEWORK_API = {
CREATE_FLOW_TEMPLATE: WORKFLOW_API_PREFIX,
};
Loading