7.5 KiB
Task for Claude: AWS Bedrock embedding setup
Objective
Prepare and verify the smallest safe AWS Bedrock integration needed to benchmark embedding models. Do not modify parsing, segmentation, table, or formula code.
Verified current state
- Repository:
D:\VSF-DUOCTHU - AWS CLI is installed and resolves credentials for IAM user
ai-lab-user. - Configured region:
us-east-1. aws sts get-caller-identitysucceeded on 2026-08-03.aws bedrock list-foundation-models --region us-east-1failed on 2026-08-03 withAccessDeniedExceptionforbedrock:ListFoundationModels.- No Bedrock embedding invocation has succeeded yet.
Models to benchmark
cohere.embed-v4:0, 1024-dimensional float embeddings.amazon.titan-embed-text-v2:0, 1024 dimensions with normalization enabled.BAAI/bge-m3local as the zero-API-cost control.
For Cohere, corpus records must use input_type=search_document; queries must
use input_type=search_query. Never mix vectors from different models in one
Qdrant collection.
Requested work
- Diagnose the current IAM restriction without exposing credentials.
- Provide or add a least-privilege IAM policy for listing and invoking only the two embedding models above. Cohere may additionally need AWS Marketplace subscription permissions for first use.
- Add provider adapters behind an interface under the existing embedding boundary; do not couple retrieval/domain code directly to Boto3.
- Add a no-cost smoke test with mocked Bedrock responses.
- Only after permissions work, make one minimal live call per cloud model and report request shape, vector dimension, latency, and actual error/success.
- Do not run full-corpus embedding yet. Leave that for the shared benchmark: 10 hard cases, then 100, then full corpus only after acceptance gates pass.
Required handoff
Update this file with:
- files changed;
- exact commands and scope run;
- observed results;
- remaining permissions or account actions required;
- anything not tested.
Handoff — Claude, 2026-08-03
Status: items 1-4 done. Item 5 (live calls) blocked on an IAM change that has not been applied. No AWS spend has occurred.
Files changed
Added:
ingestion/ingestion/embed/ports.py—EmbeddingProviderABC,EmbeddingVector,EmbeddingBatch,text_digestingestion/ingestion/embed/bedrock_runtime.py—BedrockInvokerprotocol +Boto3BedrockInvoker; the only module that imports boto3, lazilyingestion/ingestion/embed/bedrock_titan.py—amazon.titan-embed-text-v2:0ingestion/ingestion/embed/bedrock_cohere.py—cohere.embed-v4:0ingestion/ingestion/embed/local_bge_m3.py—BAAI/bge-m3local controlingestion/ingestion/embed/registry.py— name → provideringestion/ingestion/embed/probe.py— one live call, one short stringingestion/tests/test_embed_providers.py— 22 tests, all mockedinfra/aws/iam/bedrock-embedding-invoke.jsoninfra/aws/iam/bedrock-model-access-bootstrap.jsoninfra/aws/iam/README.md
Modified:
ingestion/ingestion/embed/__init__.py— was empty, now the package's public surfaceingestion/pyproject.toml— added optional extrasbedrock(boto3) andlocal-embed(sentence-transformers)
No parser, segmentation, table, formula, chunking or cli.py file was
touched. cli.py carries a pre-existing lint finding from the other
worktree owner (F401 evaluate_clinical imported but unused) which was left
alone deliberately.
Commands run and their observed results
Diagnosis (all read-only, all free):
| Command | Result |
|---|---|
aws sts get-caller-identity |
arn:aws:iam::<account>:user/ai-lab-user |
aws iam list-attached-user-policies --user-name ai-lab-user |
[] |
aws iam list-user-policies --user-name ai-lab-user |
[] |
aws iam list-groups-for-user --user-name ai-lab-user |
AI-Lab-Group |
aws iam list-attached-group-policies --group-name AI-Lab-Group |
AmazonEC2FullAccess, IAMFullAccess, ElasticLoadBalancingFullAccess, AmazonVPCFullAccess |
aws iam list-group-policies --group-name AI-Lab-Group |
[] |
aws bedrock list-foundation-models --region us-east-1 |
AccessDeniedException — bedrock:ListFoundationModels |
aws bedrock-runtime invoke-model --model-id amazon.titan-embed-text-v2:0 … |
AccessDeniedException — bedrock:InvokeModel |
Diagnosis: ai-lab-user has no inline and no attached user policy. Its one
group grants EC2, IAM, ELB and VPC full access and nothing else. There is no
bedrock:* permission anywhere on this identity — the denial is a plain
absence of grant, not an explicit Deny and not a model-access problem. No
credential value was read or printed at any point.
Tests and lint:
| Command | Scope | Result |
|---|---|---|
python -m pytest tests/test_embed_providers.py -q |
the new suite only | 22 passed |
python -m pytest -q |
whole ingestion/ suite |
203 passed (181 before this task, +22) |
python -m ruff check --select F,E9,B,ARG . |
whole ingestion/ tree |
1 error, and it is the pre-existing cli.py one above; 0 in any file added here |
python -m ingestion.embed.probe --help |
CLI wiring | parses, lists all three providers |
Request/response shapes were taken from the AWS Bedrock user guide pages "Amazon Titan Embeddings G1 - Text" (V2 tabs) and "Cohere Embed v4", both read 2026-08-03 — not from memory.
Remaining permissions / account actions required
- Create and attach
infra/aws/iam/bedrock-embedding-invoke.jsontoAI-Lab-Group(or directly toai-lab-user). Commands are ininfra/aws/iam/README.md.ai-lab-userholdsIAMFullAccess, so it can do this itself — not done here because it changes permissions on a shared company account. - Enable model access for both models in the Bedrock console (or via the
bootstrap policy).
cohere.embed-v4:0is third-party and may additionally need an AWS Marketplace subscription on first use. - Then run, one call each:
python -m ingestion.embed.probe --provider titan-v2python -m ingestion.embed.probe --provider cohere-v4
Not tested / not measured / uncertain
- No live Bedrock call has ever succeeded. Every request-body claim in
bedrock_titan.pyandbedrock_cohere.pyis documentation-derived and unproven against the service. The probe is what settles it. - Whether the drafted IAM policies are sufficient is unproven in both directions — nothing was attached, so nothing was retried.
- Whether an SCP or a permissions boundary would still block Bedrock after attachment cannot be determined from inside this identity.
bge-m3has never been run on this machine; no weights were downloaded. Its 1024 dimensions and its no-instruction-prefix property come from the published model card. The dimension is asserted at runtime, so a wrong assumption fails on the first call rather than silently.- Cohere's float vectors are recorded as
normalized=Nonebecause AWS's documentation does not state it. The probe prints a measured L2 norm, which is how that gets settled. - No embedding cost has been incurred. Nothing has been written to Qdrant. No corpus run was started.
Message the user can send Claude
Read
D:\VSF-DUOCTHU\CLAUDE.mdand everything inD:\VSF-DUOCTHU\coordination. Claim the Claude task incoordination\README.md, then perform the AWS Bedrock embedding setup exactly within that scope. Do not touch parser/chunking files and do not expose AWS credentials. Record all results back into the coordination folder.