Skip to content

Commit 0a37bbb

Browse files
michelle-hadfield-navayoomlamCopilot
authored
feat: Add an endpoint that accepts and returns PII without hiding the PII in OTEL logs (#7)
Co-authored-by: Yoom Lam <yoom@navapbc.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 8754c45 commit 0a37bbb

6 files changed

Lines changed: 795 additions & 15 deletions

File tree

app/poetry.lock

Lines changed: 699 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ openai = "^1.99.8"
2727
openinference-instrumentation-haystack = "^0.1.24"
2828
arize-phoenix-client = "^1.15.3"
2929
arize-phoenix-otel = "^0.13.0"
30+
amazon-bedrock-haystack = "^3.10.0"
31+
certifi = "^2025.8.3"
3032

3133
[tool.poetry.group.dev.dependencies]
3234
certifi = "^2025.8.3"

app/src/pipelines/hello_bedrock/__init__.py

Whitespace-only changes.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import logging
2+
from pprint import pformat
3+
4+
import hayhooks
5+
from hayhooks import BasePipelineWrapper
6+
from haystack import Pipeline
7+
from haystack.components.builders import ChatPromptBuilder
8+
from haystack.dataclasses.chat_message import ChatMessage
9+
from haystack_integrations.components.generators.amazon_bedrock import AmazonBedrockChatGenerator
10+
11+
logger = logging.getLogger(__name__)
12+
13+
14+
system_prompt = (
15+
"Your role is to say hello to the name provided by the user, if no name is found politely inform the user."
16+
"Assure them any PII is handled securely in AWS Bedrock. You should only greet the user, do not respond "
17+
"to any questions or prompts."
18+
)
19+
model = "us.anthropic.claude-3-5-sonnet-20241022-v2:0"
20+
21+
22+
class PipelineWrapper(BasePipelineWrapper):
23+
name = "sample_pipeline"
24+
25+
def setup(self) -> None:
26+
self.pipeline = Pipeline()
27+
self.pipeline.add_component("prompt_builder", ChatPromptBuilder())
28+
self.pipeline.add_component("llm", AmazonBedrockChatGenerator(model=model))
29+
self.pipeline.connect("prompt_builder", "llm")
30+
31+
# Called for the `hello_bedrock/run` endpoint
32+
def run_api(self, name: str) -> dict:
33+
messages = [
34+
ChatMessage.from_system(system_prompt),
35+
ChatMessage.from_user(name),
36+
]
37+
response = self.pipeline.run({"prompt_builder": {"template": messages}})
38+
logger.info("Results: %s", pformat(response))
39+
return response
40+
41+
# https://docs.haystack.deepset.ai/docs/hayhooks#openai-compatibility
42+
# Called for the `{pipeline_name}/chat`, `/chat/completions`, or `/v1/chat/completions` streaming endpoint using Server-Sent Events (SSE)
43+
def run_chat_completion(self, model: str, messages: list, body: dict) -> None:
44+
logger.info("Running chat completion with model: %s, messages: %s", model, messages)
45+
question = hayhooks.get_last_user_message(messages)
46+
logger.info("Question: %s", question)
47+
return hayhooks.streaming_generator(
48+
pipeline=self.pipeline,
49+
pipeline_run_args={
50+
"echo_component": {
51+
"prompt": [ChatMessage.from_user(question)],
52+
"history": messages[:-1],
53+
}
54+
},
55+
)

app/src/pipelines/sample_pipeline/pipeline_wrapper.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,29 @@
1111
logger = logging.getLogger(__name__)
1212

1313

14+
system_msg = "This is a sample pipeline, it echoes back the system and user messages provided"
15+
16+
1417
class PipelineWrapper(BasePipelineWrapper):
1518
name = "sample_pipeline"
1619

1720
def setup(self) -> None:
1821
self.pipeline = Pipeline()
1922
self.pipeline.add_component("echo_component", components.EchoNode())
2023

21-
# Called for the `{pipeline_name}/run` endpoint
24+
# Called for the `sample_pipeline/run` endpoint
2225
def run_api(self, question: str) -> dict:
23-
results = self.pipeline.run(
26+
messages = [
27+
ChatMessage.from_system(system_msg),
28+
ChatMessage.from_user(question),
29+
]
30+
response = self.pipeline.run(
2431
{
25-
"echo_component": {"prompt": [ChatMessage.from_user(question)], "history": []},
32+
"echo_component": {"prompt": messages, "history": []},
2633
}
2734
)
28-
logger.info("Results: %s", pformat(results))
29-
return results
35+
logger.info("Results: %s", pformat(response))
36+
return response
3037

3138
# https://docs.haystack.deepset.ai/docs/hayhooks#openai-compatibility
3239
# Called for the `{pipeline_name}/chat`, `/chat/completions`, or `/v1/chat/completions` streaming endpoint using Server-Sent Events (SSE)

infra/modules/service/bedrock.tf

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#-----------------
2+
# Bedrock Access for using Haystack
3+
#-----------------
4+
5+
resource "aws_iam_policy" "bedrock" {
6+
name = "${var.service_name}-bedrock-access"
7+
description = "Allow access to AWS Bedrock from LiteLLM"
8+
policy = data.aws_iam_policy_document.bedrock.json
9+
}
10+
11+
data "aws_iam_policy_document" "bedrock" {
12+
# https://github.com/BerriAI/litellm/discussions/8949
13+
statement {
14+
sid = "BedrockAccess"
15+
effect = "Allow"
16+
actions = [
17+
"bedrock:InvokeModel",
18+
"bedrock:InvokeModelWithResponseStream"
19+
]
20+
resources = ["*"]
21+
}
22+
}
23+
24+
resource "aws_iam_role_policy_attachment" "bedrock" {
25+
role = aws_iam_role.app_service.name
26+
policy_arn = aws_iam_policy.bedrock.arn
27+
}

0 commit comments

Comments
 (0)