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

Plfm 8720 #687

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import static org.sagebionetworks.template.TemplateUtils.loadFromJsonFile;

import java.io.IOException;
import java.time.Duration;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.sagebionetworks.template.Constants.PROPERTY_KEY_STACK;

import java.util.StringJoiner;
import java.util.UUID;

import org.apache.velocity.VelocityContext;
import org.json.JSONArray;
Expand All @@ -12,23 +13,33 @@
import org.sagebionetworks.template.config.RepoConfiguration;
import org.sagebionetworks.template.repo.VelocityContextProvider;

import com.amazonaws.services.s3.AmazonS3Client;
import com.google.inject.Inject;

public class BedrockAgentContextProvider implements VelocityContextProvider {

private final RepoConfiguration repoConfig;
private final AmazonS3Client s3Cient;

@Inject
public BedrockAgentContextProvider(RepoConfiguration repoConfig) {
public BedrockAgentContextProvider(RepoConfiguration repoConfig, AmazonS3Client s3Client) {
super();
this.repoConfig = repoConfig;
this.s3Cient = s3Client;
}

@Override
public void addToContext(VelocityContext context) {
String stack = repoConfig.getProperty(PROPERTY_KEY_STACK);
String instance = repoConfig.getProperty(PROPERTY_KEY_INSTANCE);
String agentName = new StringJoiner("-").add(stack).add(instance).add("agent").toString();

String openApiSchemaBucket = String.format("%s-configuration.sagebase.org", stack);
String openApiSchemakey = String.format("chat/openapi/%s/%s.json", instance, UUID.randomUUID().toString());

String openApiSchemJsonString = TemplateUtils.loadContentFromFile("templates/repo/agent/agent_open_api.json");
s3Cient.putObject(openApiSchemaBucket, openApiSchemakey, openApiSchemJsonString);


JSONObject baseTemplate = new JSONObject(TemplateUtils.loadContentFromFile("templates/repo/agent/bedrock_agent_template.json"));

Expand Down Expand Up @@ -60,6 +71,11 @@ public void addToContext(VelocityContext context) {
kbProperty.getJSONObject("KnowledgeBaseId").put("Ref", "SynapseHelpKnowledgeBase");
kbProperty.put("Description", baseTemplate.getJSONObject("Parameters").getJSONObject("knowledgeBaseDescription").getString("Default"));

JSONObject s3 = bedrockAgentProps.getJSONArray("ActionGroups").getJSONObject(1).getJSONObject("ApiSchema")
.getJSONObject("S3");
s3.put("S3BucketName", openApiSchemaBucket);
s3.put("S3ObjectKey", openApiSchemakey);

bedrockAgentProps.put("AgentName", agentName);
String json = resources.toString();
context.put("bedrock_agent_resouces", "," + json.substring(1, json.length()-1));
Expand Down
137 changes: 137 additions & 0 deletions src/main/resources/templates/repo/agent/agent_open_api.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"openapi": "3.0.0",
"info": {
"title": "CRUD Opperations Schema",
"version": "v1"
},
"paths": {
"/entity/{entityId}/annotations": {
"get": {
"description": "Get the annotations of an entity.",
"operationId": "orgSageOneEntityAnnotationsGet",
"parameters": [
{
"name": "entityId",
"description": "The 'syn' Id of the entity to get the annotations for.",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Auto-generated description",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/org.sagebionetworks.repo.model.annotation.v2.Annotations"
}
}
}
}
}
},
"put": {
"description": "Set the annotations of an entity.",
"operationId": "orgSageOneEntityAnnotationsPut",
"x-requireConfirmation": "ENABLED",
"parameters": [
{
"name": "entityId",
"description": "The 'syn' of the target Entity.",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/org.sagebionetworks.repo.model.annotation.v2.Annotations"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "the updated annotations",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/org.sagebionetworks.repo.model.annotation.v2.Annotations"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"org.sagebionetworks.repo.model.annotation.v2.Annotations": {
"type": "object",
"description": "Each annotation is a key-value pair of metadata for an Entity.",
"properties": {
"id": {
"type": "string",
"description": "The 'syn' ID of the Entity"
},
"etag": {
"type": "string",
"description": "The current etag of the Entity. The etag of an Entity will change each time an Entity is updated. An annotations update request will be rejected if provided etag does not match the current etag of the Entity."
},
"annotations": {
"type": "object",
"description": "Annotations are a map of key-value pairs. The key is the name of the annotation. The value is an object.",
"additionalProperties": {
"$ref": "#/components/schemas/org.sagebionetworks.repo.model.annotation.v2.AnnotationsValue"
}
}
},
"required": [
"id",
"etag",
"annotations"
]
},
"org.sagebionetworks.repo.model.annotation.v2.AnnotationsValue": {
"type": "object",
"description": "This object defines the value of an annotation.",
"properties": {
"type": {
"$ref": "#/components/schemas/org.sagebionetworks.repo.model.annotation.v2.AnnotationsValueType"
},
"value": {
"type": "array",
"description": "The annotation's value must include one or more strings. See the 'type' to determine how each string should be parsed. An empty array is not allowed.",
"items": {
"type": "string"
}
}
},
"required": [
"type",
"value"
]
},
"org.sagebionetworks.repo.model.annotation.v2.AnnotationsValueType": {
"type": "string",
"description": "The annotation's type defines how each string value should be parsed.",
"enum": [
"STRING",
"DOUBLE",
"LONG",
"TIMESTAMP_MS",
"BOOLEAN"
]
}
}
}
}
98 changes: 76 additions & 22 deletions src/main/resources/templates/repo/agent/bedrock_agent_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,32 @@
"Type": "String",
"Default": "This knowledge base contains the Synapse help documentation. You can use it to answer questions around Synapse usage and its features.",
"MaxLength": 200
},
"openApiSchemaS3Bucket": {
"Description": "The name of the S3 bucket containing the Open API Schema definition JSON file.",
"Type": "String",
"AllowedPattern": "^([0-9a-zA-Z][_-]?){1,100}$"
},
"openApiSchemaS3Key": {
"Description": "The S3 key of the Open API Schema definition JSON file.",
"Type": "String",
"AllowedPattern": "^([0-9a-zA-Z][_-]?){1,100}$"
}
},
"Conditions": {
"AttachKnowledgeBase": {"Fn::Not": [{"Fn::Equals" : [{"Ref" : "knowledgeBaseId"}, ""]}]}
},
"AttachKnowledgeBase": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "knowledgeBaseId"
},
""
]
}
]
}
},
"Resources": {
"bedrockAgentRole": {
"Type": "AWS::IAM::Role",
Expand Down Expand Up @@ -59,7 +80,7 @@
"Statement": [
{
"Effect": "Allow",
"Action": [
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
Expand All @@ -70,23 +91,29 @@
]
},
{
"Fn::If" : [ "AttachKnowledgeBase",
"Fn::If": [
"AttachKnowledgeBase",
{
"Effect": "Allow",
"Action": [
"bedrock:Retrieve",
"bedrock:RetrieveAndGenerate"
],
"Resource": [
"Effect": "Allow",
"Action": [
"bedrock:Retrieve",
"bedrock:RetrieveAndGenerate"
],
"Resource": [
{
"Fn::Sub": "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/${knowledgeBaseId}"
}
]
},
]
},
{
"Ref" : "AWS::NoValue"
"Ref": "AWS::NoValue"
}
]
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
Expand Down Expand Up @@ -164,25 +191,52 @@
]
},
"SkipResourceInUseCheckOnDelete": false
},
{
"ActionGroupExecutor": {
"CustomControl": "RETURN_CONTROL"
},
"ActionGroupName": "org_sage_one",
"ActionGroupState": "ENABLED",
"Description": "These functions can be used to make data changes in Synapse.",
"ApiSchema": {
"S3": {
"S3BucketName": {
"Ref": "openApiSchemaS3Bucket"
},
"S3ObjectKey": {
"Ref": "openApiSchemaS3Key"
}
}
}
}
],
"AgentName": { "Ref" : "agentName" },
"AgentName": {
"Ref": "agentName"
},
"AgentResourceRoleArn": {
"Fn::GetAtt": [
"bedrockAgentRole",
"Arn"
]
},
"KnowledgeBases": {
"Fn::If" : [ "AttachKnowledgeBase",
[{
"KnowledgeBaseId" : { "Ref" : "knowledgeBaseId" },
"Description" : { "Ref" : "knowledgeBaseDescription" }
}],
"Fn::If": [
"AttachKnowledgeBase",
[
{
"KnowledgeBaseId": {
"Ref": "knowledgeBaseId"
},
"Description": {
"Ref": "knowledgeBaseDescription"
}
}
],
{
"Ref" : "AWS::NoValue"
}
]
"Ref": "AWS::NoValue"
}
]
},
"AutoPrepare": true,
"Description": "Test of the use of actions groups to allow the agent to make Synapse API calls.",
Expand Down
Loading
Loading