Skip to content

Commit 185587e

Browse files
authored
Release v5.2.0 into Main
2 parents c389d04 + 8df62e4 commit 185587e

File tree

90 files changed

+5577
-933
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+5577
-933
lines changed

.github/workflows/code.end-to-end-test.nightly.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ jobs:
3636
cache: 'npm'
3737
- name: Install base dependencies
3838
run: npm ci
39-
- name: Install Cypress deps
40-
run: npm ci --prefix cypress
4139
- name: Run Cypress E2E Suite
4240
env:
4341
TEST_ACCOUNT_PASSWORD: ${{ secrets.TEST_ACCOUNT_PASSWORD }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ lib/rag/ingestion/ingestion-image/build
2929
.DS_Store
3030
*.iml
3131
*.code-workspace
32+
.cursor
33+
memory-bank/
3234

3335
# Coverage Statistic Folders
3436
coverage

.pre-commit-config.yaml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ repos:
1212
files: config.yaml
1313

1414
- repo: https://github.com/PyCQA/bandit
15-
rev: '1.7.5'
15+
rev: '1.7.10'
1616
hooks:
1717
- id: bandit
1818
args: [--recursive, -c=pyproject.toml]
19-
additional_dependencies: ['bandit[toml]']
19+
additional_dependencies: ['bandit[toml]', 'pbr']
2020

2121
- repo: https://github.com/Yelp/detect-secrets
22-
rev: v1.4.0
22+
rev: v1.5.0
2323
hooks:
2424
- id: detect-secrets
2525
exclude: (?x)^(
2626
.*.ipynb|config.yaml|.*.md|.*test.*.py
2727
)$
2828

2929
- repo: https://github.com/pre-commit/pre-commit-hooks
30-
rev: v4.5.0
30+
rev: v5.0.0
3131
hooks:
3232
- id: check-json
3333
- id: check-yaml
@@ -41,15 +41,15 @@ repos:
4141
- id: trailing-whitespace
4242

4343
- repo: https://github.com/codespell-project/codespell
44-
rev: v2.2.6
44+
rev: v2.3.0
4545
hooks:
4646
- id: codespell
4747
entry: codespell
4848
args: ['--skip=*.git*,*cdk.out*,*venv*,*mypy_cache*,*package-lock*,*node_modules*,*dist/*,*poetry.lock*,*coverage*,*models/*,*htmlcov*,*TIKTOKEN_CACHE/*', "-L=xdescribe"]
4949
pass_filenames: false
5050

5151
- repo: https://github.com/pycqa/isort
52-
rev: 5.12.0
52+
rev: 5.13.2
5353
hooks:
5454
- id: isort
5555
name: isort (python)
@@ -59,13 +59,14 @@ repos:
5959
hooks:
6060
- id: black
6161

62-
- repo: https://github.com/charliermarsh/ruff-pre-commit
63-
rev: 'v0.1.3'
62+
- repo: https://github.com/astral-sh/ruff-pre-commit
63+
rev: 'v0.8.4'
6464
hooks:
6565
- id: ruff
6666
args:
6767
- --exit-non-zero-on-fix
6868
- --per-file-ignores=test/**/*.py:E402
69+
exclude: \.ipynb$
6970

7071
- repo: https://github.com/pycqa/flake8
7172
rev: '7.1.1'
@@ -85,7 +86,7 @@ repos:
8586

8687

8788
- repo: https://github.com/pre-commit/mirrors-mypy
88-
rev: 'v1.6.1'
89+
rev: 'v1.13.0'
8990
hooks:
9091
- id: mypy
9192
verbose: true

CHANGELOG.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
# v5.2.0
2+
## Key Features
3+
### Model Context Protocol (MCP) Enhancements
4+
- **Connection Validation**: Real-time connection testing with detailed feedback on server connectivity during connection creation/edit
5+
- **Enhanced Debugging**: Improved error handling and connection status reporting for MCP servers
6+
7+
### Session Management Improvements
8+
- **Time-Based Session Grouping**: Sessions are now automatically organized into time-based groups based on updated date (Last Day, Last 7 Days, Last Month, Last 3 Months, Older)
9+
- **Session ID Removal**: Removed session ID from prompt input for cleaner user interface
10+
11+
### RAG (Retrieval-Augmented Generation) Improvements
12+
#### Document Processing
13+
- **Document Chunk Processing Fixes**: Resolved issues with document chunk processing and ingestion
14+
- **Document Library Pagination**: Added pagination support for the Document Library to handle large numbers of documents efficiently
15+
16+
#### Vector Store Configuration
17+
- **Default Embedding Model Support**: Added ability to define a default embedding model when creating or updating vector stores
18+
- **IAM Permissions Optimization**: Trimmed vector store IAM permissions to follow the principle of least privilege
19+
- **Container Configuration**: Added container override configuration for batch ingestion processes
20+
21+
#### Batch Ingestion
22+
- **Container Configuration**: Added support for container override configuration in batch ingestion jobs
23+
- **Max Batch Jobs Setting**: Implemented dynamic maximum batch jobs limit
24+
- **Ingestion Rules Updates**: Automatic updates to ingestion rules when Lambda functions are updated
25+
26+
### Model Management Improvements
27+
- **Base Container Configuration**: Added support for using prebuilt model containers, instead of building during model deployment
28+
29+
### UI/UX Enhancements
30+
- **General UI Improvements**: Various user interface enhancements to improve usability
31+
- **Updated Default System Prompt**: Updated LISAs default system prompt to take advantage of new rendering capabilities. Pairing this prompt with new UI components supports the display of:
32+
- Inline-Code
33+
- Mathematic equations using LaTex syntax
34+
- Mermaid Diagrams. These diagrams can also be copied and downloaded as images
35+
36+
## Acknowledgements
37+
* @bedanley
38+
* @estohlmann
39+
* @dustins
40+
* @jmharold
41+
42+
**Full Changelog**: https://github.com/awslabs/LISA/compare/v5.1.0...v5.2.0
43+
144
# v5.1.0
245
## Key Features
346
### Model Management Enhancements

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.1.0
1+
5.2.0

lambda/mcp_server/lambda_functions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
import boto3
2323
from boto3.dynamodb.conditions import Attr, Key
24-
from utilities.common_functions import api_wrapper, get_item, get_username, is_admin, retry_config
24+
from utilities.auth import get_username, is_admin
25+
from utilities.common_functions import api_wrapper, get_item, retry_config
2526

2627
from .models import McpServerModel, McpServerStatus
2728

lambda/models/domain_objects.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,9 @@ class RagDocument(BaseModel):
432432
def __init__(self, **data: Any) -> None:
433433
super().__init__(**data)
434434
self.pk = self.createPartitionKey(self.repository_id, self.collection_id)
435-
self.chunks = len(self.subdocs)
435+
# Only calculate chunks if not explicitly provided in data (for new documents)
436+
if "chunks" not in data:
437+
self.chunks = len(self.subdocs)
436438

437439
@staticmethod
438440
def createPartitionKey(repository_id: str, collection_id: str) -> str:

lambda/models/lambda_functions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
from fastapi.middleware.cors import CORSMiddleware
2525
from fastapi.responses import JSONResponse
2626
from mangum import Mangum
27-
from utilities.common_functions import get_groups, is_admin, retry_config
27+
from utilities.auth import is_admin
28+
from utilities.common_functions import get_groups, retry_config
2829
from utilities.fastapi_middleware.aws_api_gateway_middleware import AWSAPIGatewayMiddleware
2930

3031
from .domain_objects import (

lambda/models/state_machine/create_model.py

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,49 @@ def handle_start_copy_docker_image(event: Dict[str, Any], context: Any) -> Dict[
117117
image_path = get_container_path(request.inferenceContainer)
118118
output_dict["containerConfig"]["image"]["path"] = image_path
119119

120+
# Check if image type is ECR - skip building docker image if it already exists
121+
if request.containerConfig and request.containerConfig.image.type == "ecr":
122+
logger.info(f"ECR image detected for model {event.get('modelId')}, verifying image accessibility")
123+
# Verify the ECR image is accessible
124+
try:
125+
# Extract repository name and tag from the base image
126+
base_image = request.containerConfig.image.baseImage
127+
if ":" in base_image:
128+
repository_name, image_tag = base_image.rsplit(":", 1)
129+
else:
130+
repository_name = base_image
131+
image_tag = "latest"
132+
133+
# Remove registry URL if present to get just the repository name
134+
if "/" in repository_name:
135+
repository_name = repository_name.split("/")[-1]
136+
137+
# Verify image exists in ECR
138+
ecrClient.describe_images(repositoryName=repository_name, imageIds=[{"imageTag": image_tag}])
139+
140+
logger.info(f"ECR image {base_image} verified successfully")
141+
output_dict["image_info"] = {
142+
"image_tag": image_tag,
143+
"image_uri": repository_name,
144+
"image_type": "ecr",
145+
"remaining_polls": 0,
146+
"image_status": "prebuilt",
147+
}
148+
return output_dict
149+
150+
except ecrClient.exceptions.ImageNotFoundException:
151+
error_msg = f"ECR image {base_image} not found. Please ensure the image exists and is accessible."
152+
logger.error(error_msg)
153+
raise Exception(error_msg)
154+
except ecrClient.exceptions.RepositoryNotFoundException:
155+
error_msg = (
156+
f"ECR repository {repository_name} not found. Please ensure the repository exists and is accessible."
157+
)
158+
logger.error(error_msg)
159+
raise Exception(error_msg)
160+
161+
# For non-ECR images, proceed with the normal docker image building process
162+
logger.info(f"Invoking image build for model {event.get('modelId')}")
120163
response = lambdaClient.invoke(
121164
FunctionName=os.environ["DOCKER_IMAGE_BUILDER_FN_ARN"],
122165
Payload=json.dumps(
@@ -130,6 +173,7 @@ def handle_start_copy_docker_image(event: Dict[str, Any], context: Any) -> Dict[
130173
payload = response["Payload"].read()
131174
output_dict["image_info"] = json.loads(payload)
132175
output_dict["image_info"]["remaining_polls"] = 30
176+
output_dict["image_info"]["image_status"] = "building"
133177
return output_dict
134178

135179

@@ -138,14 +182,22 @@ def handle_poll_docker_image_available(event: Dict[str, Any], context: Any) -> D
138182
output_dict = deepcopy(event)
139183

140184
try:
185+
# Use the appropriate repository name based on image type
186+
repository_name = (
187+
event["image_info"]["image_uri"]
188+
if event["image_info"].get("image_type") == "ecr"
189+
else os.environ["ECR_REPOSITORY_NAME"]
190+
)
141191
ecrClient.describe_images(
142-
repositoryName=os.environ["ECR_REPOSITORY_NAME"], imageIds=[{"imageTag": event["image_info"]["image_tag"]}]
192+
repositoryName=repository_name, imageIds=[{"imageTag": event["image_info"]["image_tag"]}]
143193
)
144194
except ecrClient.exceptions.ImageNotFoundException:
145195
output_dict["continue_polling_docker"] = True
146196
output_dict["image_info"]["remaining_polls"] -= 1
147197
if output_dict["image_info"]["remaining_polls"] <= 0:
148-
ec2Client.terminate_instances(InstanceIds=[event["image_info"]["instance_id"]])
198+
# Only terminate EC2 instance if one exists (not for pre-existing ECR images)
199+
if "instance_id" in event["image_info"]:
200+
ec2Client.terminate_instances(InstanceIds=[event["image_info"]["instance_id"]])
149201
raise MaxPollsExceededException(
150202
json.dumps(
151203
{
@@ -157,7 +209,9 @@ def handle_poll_docker_image_available(event: Dict[str, Any], context: Any) -> D
157209
return output_dict
158210

159211
output_dict["continue_polling_docker"] = False
160-
ec2Client.terminate_instances(InstanceIds=[event["image_info"]["instance_id"]])
212+
# Only terminate EC2 instance if one exists (not for pre-existing ECR images)
213+
if "instance_id" in event["image_info"]:
214+
ec2Client.terminate_instances(InstanceIds=[event["image_info"]["instance_id"]])
161215
return output_dict
162216

163217

@@ -178,11 +232,32 @@ def camelize_object(o): # type: ignore[no-untyped-def]
178232

179233
prepared_event = camelize_object(event)
180234
prepared_event["containerConfig"]["environment"] = event["containerConfig"]["environment"]
181-
prepared_event["containerConfig"]["image"] = {
182-
"repositoryArn": os.environ["ECR_REPOSITORY_ARN"],
183-
"tag": event["image_info"]["image_tag"],
184-
"type": "ecr",
185-
}
235+
236+
# Handle ECR images differently - use the existing ECR image instead of the built one
237+
if event["image_info"].get("image_type") == "ecr":
238+
# For pre-existing ECR images, construct the ARN using the image repository
239+
account_id = os.environ.get("AWS_ACCOUNT_ID", "")
240+
if not account_id:
241+
# Try to get account ID from the existing ECR repository ARN
242+
ecr_repo_arn = os.environ.get("ECR_REPOSITORY_ARN", "")
243+
if ecr_repo_arn:
244+
account_id = ecr_repo_arn.split(":")[4]
245+
246+
repository_arn = (
247+
f"arn:aws:ecr:{os.environ['AWS_REGION']}:{account_id}:repository/{event['image_info']['image_uri']}"
248+
)
249+
prepared_event["containerConfig"]["image"] = {
250+
"repositoryArn": repository_arn,
251+
"tag": event["image_info"]["image_tag"],
252+
"type": "ecr",
253+
}
254+
else:
255+
# For built images, use the default ECR repository
256+
prepared_event["containerConfig"]["image"] = {
257+
"repositoryArn": os.environ["ECR_REPOSITORY_ARN"],
258+
"tag": event["image_info"]["image_tag"],
259+
"type": "ecr",
260+
}
186261

187262
response = lambdaClient.invoke(
188263
FunctionName=os.environ["ECS_MODEL_DEPLOYER_FN_ARN"],

lambda/prompt_templates/lambda_functions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
import boto3
2424
from boto3.dynamodb.conditions import Attr, Key
25-
from utilities.common_functions import api_wrapper, get_groups, get_item, get_username, is_admin, retry_config
25+
from utilities.auth import get_username, is_admin
26+
from utilities.common_functions import api_wrapper, get_groups, get_item, retry_config
2627

2728
from .models import PromptTemplateModel
2829

0 commit comments

Comments
 (0)