diff --git a/Dockerfile.agentcore-runtime b/Dockerfile.agentcore-runtime new file mode 100644 index 0000000..19e0a85 --- /dev/null +++ b/Dockerfile.agentcore-runtime @@ -0,0 +1,25 @@ +# 5-Agent 리포트 생성 Graph를 AgentCore Runtime으로 호스팅하는 이미지. +# report_generation.deployment:agentcore_entrypoint가 하는 일(Strands Graph +# 실행, RDS 조회, Bedrock 호출, AgentCore Gateway 경유 검색)은 KURE 임베딩 +# 모델이 필요 없으므로 cpu-worker(Dockerfile.cpu)의 무거운 ML extra(torch, +# sentence-transformers 등)는 설치하지 않는다 - base 의존성만으로 충분하다. +FROM python:3.11-slim + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +WORKDIR /app + +COPY pyproject.toml uv.lock ./ +RUN uv sync --frozen --no-dev + +COPY app ./app + +ENV PYTHONPATH=/app +ENV PATH="/app/.venv/bin:$PATH" + +EXPOSE 8080 + +RUN adduser --disabled-password --uid 1000 appuser +USER 1000 + +CMD ["python", "-m", "app.agents.report_generation.deployment"] diff --git a/app/agents/report_generation/deployment.py b/app/agents/report_generation/deployment.py index c92b25b..1adccec 100644 --- a/app/agents/report_generation/deployment.py +++ b/app/agents/report_generation/deployment.py @@ -57,3 +57,9 @@ def create_agentcore_runtime(): app = BedrockAgentCoreApp() app.entrypoint(agentcore_entrypoint) return app + + +if __name__ == "__main__": + # AgentCore Runtime 컨테이너의 CMD 진입점. AWS의 invocation 프로토콜에 맞춰 + # BedrockAgentCoreApp이 자체적으로 8080 포트에 /invocations, /ping을 서빙한다. + create_agentcore_runtime().run() diff --git a/pyproject.toml b/pyproject.toml index c6c14ab..9b7e3e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ dependencies = [ "opentelemetry-instrumentation-httpx>=0.50b0", "opentelemetry-instrumentation-sqlalchemy>=0.50b0", "opentelemetry-instrumentation-botocore>=0.50b0", + "bedrock-agentcore>=1.17.0", ] [project.optional-dependencies] diff --git a/uv.lock b/uv.lock index a89621c..53959b9 100644 --- a/uv.lock +++ b/uv.lock @@ -446,32 +446,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, ] +[[package]] +name = "bedrock-agentcore" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "botocore" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "urllib3" }, + { name = "uvicorn" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/ae/38e870cd7f73ba41ab78ca1fef9b40e0b8a486498e8978965ce65bde61f3/bedrock_agentcore-1.17.0.tar.gz", hash = "sha256:dc237d313ffd6b1fc5547ff334ed7aa160b469bc086b20f0f8679d18d75cf20d", size = 939469, upload-time = "2026-07-02T15:42:27.032Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/c7/d80bcb9ba295485f27affe3405a45c71ad4bf82d547715b82ae47206d478/bedrock_agentcore-1.17.0-py3-none-any.whl", hash = "sha256:ef1c3acd3f1bd2bd5a01b0cd70510a4c8ca999abe87f9c43fa52e68484776815", size = 431835, upload-time = "2026-07-02T15:42:25.209Z" }, +] + [[package]] name = "boto3" -version = "1.43.24" +version = "1.43.40" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/8f/94dfa39ec618ecb2fe5b5b79428c95100e3ae3c1aa5083c283dd3cfb5ecd/boto3-1.43.24.tar.gz", hash = "sha256:ba5afa266bf7265e0c1a454fcfd48bffe5939cb16ed223bebc669c3dc8ee0bc8", size = 113154, upload-time = "2026-06-05T19:30:01.635Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/43/38cdaf9c7bb50f0922ef87e6b6696c6aa589d978e4311a8287537e84ecf7/boto3-1.43.40.tar.gz", hash = "sha256:a7108b9ce25b8f92d1ce96b9e35090794d5c58b219ff2f6a7a65c8986a4ed6f4", size = 112655, upload-time = "2026-07-03T00:28:26.776Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/b7/e66c9b37b96153aa371fe48d24194151293f6577dd3eaa1fc146c281456d/boto3-1.43.24-py3-none-any.whl", hash = "sha256:b18ef745274ef548a9660d733d985d4a971b16bd8a6af88165ea9d0e40913b86", size = 140536, upload-time = "2026-06-05T19:29:58.968Z" }, + { url = "https://files.pythonhosted.org/packages/d7/3b/2abcc7f47e955a8cb45a6378ec69cd8ed2dcb3d14ceb67717dea020a794a/boto3-1.43.40-py3-none-any.whl", hash = "sha256:5fa80de4b4b7bab383dd8c563e235d51fcc7df4502662af56f0a2472c3c15651", size = 140029, upload-time = "2026-07-03T00:28:25.028Z" }, ] [[package]] name = "botocore" -version = "1.43.24" +version = "1.43.40" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/67/55d0611b341482bc9649d16df765f849a1862184ac3709356decf632279f/botocore-1.43.24.tar.gz", hash = "sha256:0c02f2b40e99419d496ece0ea2dcdedb5c45998c16fd1674276c7dbb30767a16", size = 15471690, upload-time = "2026-06-05T19:29:33.731Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/50/269986277f852cc83029bccbdcdc0b343a685cfd570599e58029792808d8/botocore-1.43.40.tar.gz", hash = "sha256:2085a4314cfd2c8bc1d08ab8039f76c92e99278db0d2a0e2437010526d5d5d70", size = 15639899, upload-time = "2026-07-03T00:28:16.125Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/b7/360b5afe74c4d7cff871ea6e8f335e2e11de2945c9deb1eea6438f49faa2/botocore-1.43.24-py3-none-any.whl", hash = "sha256:42903b4bfafd8f15a735ed940473f28e4ba21b2ea67a9b9aaa11dfa7fcb19fd5", size = 15155182, upload-time = "2026-06-05T19:29:29.457Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8c/5f7e73fd66b28f0705bc55d7060d41ef72328b656b86ca53e75765b3ba2c/botocore-1.43.40-py3-none-any.whl", hash = "sha256:0bc9d352267c9e48415c5d7bb61ff05c3f193eac2fc7e69cfd229a05fbab67d6", size = 15323870, upload-time = "2026-07-03T00:28:12.56Z" }, ] [package.optional-dependencies] @@ -4637,14 +4656,14 @@ wheels = [ [[package]] name = "s3transfer" -version = "0.18.0" +version = "0.19.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/1f/12417f7f493fc45e1f9fd5d4a9b6c125cf8d2cf3f8ddbdfab3e76406e9d6/s3transfer-0.18.0.tar.gz", hash = "sha256:3760b8b7ec1315da54048b2d626276732bee4300d054d492d4e1d43e20d4ecbd", size = 160560, upload-time = "2026-05-28T19:39:09.124Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/94/dcdaeb1713cab9c84def276cfac7388b17c7d9855bbcfe88d77e4dbafd44/s3transfer-0.19.0.tar.gz", hash = "sha256:ce436931687addc4c1712d52d40b32f53e88315723f107ffa20ba82b05a0f685", size = 165171, upload-time = "2026-06-16T19:44:51.599Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/58/a58fc997655386daa2e25784e30c288aa3e3819e401f77029ee4899fb55a/s3transfer-0.18.0-py3-none-any.whl", hash = "sha256:239c13b09e65ad0346e1be7348b8a202dcad44ac7ea7c6eb858fc881dce739b6", size = 88572, upload-time = "2026-05-28T19:39:07.999Z" }, + { url = "https://files.pythonhosted.org/packages/46/5f/4c174edad94f82de888ac00a5ddd8d07b35609b6c94f0bdf4d74af57703e/s3transfer-0.19.0-py3-none-any.whl", hash = "sha256:777cc2415536f1debadb5c2ef7779275d0fc0fe0e042411cdd6caebeb2685262", size = 90101, upload-time = "2026-06-16T19:44:50.439Z" }, ] [[package]] @@ -5413,6 +5432,7 @@ name = "utterai-ai" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "bedrock-agentcore" }, { name = "boto3" }, { name = "fastapi" }, { name = "kiwipiepy" }, @@ -5479,6 +5499,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "accelerate", marker = "extra == 'gpu'", specifier = ">=0.30.0" }, + { name = "bedrock-agentcore", specifier = ">=1.17.0" }, { name = "boto3", specifier = ">=1.34.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "faster-whisper", marker = "extra == 'gpu'", specifier = ">=1.1.0" },