aws

Kari Marttila 2025-02-20T15:32:39.958589Z

What is the best way to call AWS Bedrock model (retrieve and generate) using a foundation model (anthropic.claude-v2) in clojure? β€’ Java SKD (example: https://docs.aws.amazon.com/code-library/latest/ug/java_2_bedrock-runtime_code_examples.html#anthropic_claude) β€’ Cognitect AWS API (example: https://mvnrepository.com/artifact/com.cognitect.aws/bedrock-agent-runtime)

Kari Marttila 2025-02-20T15:34:34.240819Z

If I get help and make this Clojure backend work, I promise to write a blog post, e.g. "Using Clojure with GenAI" in my blog: https://www.karimarttila.fi/ πŸ™‚

Kari Marttila 2025-02-20T15:53:36.377089Z

I.e. the same call as e.g. in Python:

def getAnswer(question):
        knowledgeBaseResponse  = bedrock_client.retrieve_and_generate(
            input={'text': question},
            retrieveAndGenerateConfiguration={
                'knowledgeBaseConfiguration': {
                    'knowledgeBaseId': knowledgebase_id,
                    'modelArn': model_arn
                },
                'type': 'KNOWLEDGE_BASE'
            })
        return knowledgeBaseResponse

Kari Marttila 2025-02-20T15:55:38.108309Z

Let's experiment with the aws api...

(require '[cognitect.aws.client.api :as aws]) 
  (def bedrock (aws/client {:api :bedrock-agent-runtime})) 
  (def bedrock-doc (aws/ops bedrock)) 
  (type bedrock-doc)
  (keys bedrock-doc)
  ;;=> (:OptimizePrompt
...
  ;;    :RetrieveAndGenerate       => HAA! There it is!

Kari Marttila 2025-02-20T16:23:11.404699Z

Γ–ΓΆ... was it that easy?

(let [request {:input {:text my-question}
                 :retrieveAndGenerateConfiguration 
                 {:knowledgeBaseConfiguration 
                  {
                   :knowledgeBaseId knowledge-base-id
                   :modelArn model-arn
                   }
                  :type bedrock-query-type
                  }
                 :session-id "s1"
                 }
        response (aws/invoke bedrock
                             {:op :RetrieveAndGenerate
                              :request request})]
    response)
  ;;=> {:citations
  ;;    [{:generatedResponsePart
...

Kari Marttila 2025-02-20T16:23:30.994909Z

I can't believe it. I did it without any help.

πŸŽ‰ 2
Kari Marttila 2025-02-20T16:24:03.070089Z

Damn. It was so cool to use Clojure REPL / editor integration to examine the docs.

1
scottbale 2025-02-21T01:12:12.969329Z

@kari.marttila glad to see you had a good outcome with aws-api! > Damn. It was so cool to use Clojure REPL / editor integration to examine the docs. Yeah, data and REPL-driven workflow was a goal from the very start of the project. :)

πŸ‘ 1
❀️ 1
Kari Marttila 2025-02-21T07:04:05.055099Z

Is it ok in my backend to create a var for the aws-client, like this:

(def bedrock-client (aws/client {:api :bedrock-agent-runtime}))
I guess it does not make sense to create a new client per every request? I.e., does the aws client take care of refreshing the connection, etc.?

scottbale 2025-02-21T14:18:55.728789Z

Yes it is okay if you are using aws-api version 0.8.711 or newer and the default java.net.http-based underlying http client. In that case, the aws-api's client's key piece of state is an instance of .http.HttpClient, which manages its own resources. Even if you don't def your connection, the default behavior is that a single shared instance of the java.net.http-based underlying http client is shared among any created aws-api clients. (This can be overridden.) Prior to version 0.8.711, the old Jetty 9-based http client was used. The answer is mostly the same there but there are some caveats https://github.com/cognitect-labs/aws-api/blob/main/UPGRADE.md#08430.

πŸ‘ 1