davsclaus commented on code in PR #25337:
URL: https://github.com/apache/camel/pull/25337#discussion_r3723053535


##########
docs/components/modules/others/nav.adoc:
##########
@@ -4,6 +4,7 @@
 * xref:others:index.adoc[Miscellaneous Components]
 ** xref:a2a-consumer.adoc[A2A - Consumer Guide]
 ** xref:a2a-producer.adoc[A2A - Producer Guide]
+*** xref:ai-observability.adoc[AI Observability]
 ** xref:attachments.adoc[Attachments]
 ** xref:aws-bedrock-examples.adoc[AWS Bedrock - Examples]

Review Comment:
   **[High]** This file is auto-generated (see line 1–2: _"this file is auto 
generated and changes to it will be overwritten"_). The entry should be 
generated automatically by the build from the module's doc structure. Remove 
this manual edit.
   
   Additionally, the nesting level is wrong: `***` (three stars) makes this a 
sub-item of "A2A - Producer Guide" instead of a peer entry at the `**` level.



##########
components/camel-ai/camel-langchain4j-agent/src/main/java/org/apache/camel/component/langchain4j/agent/LangChain4jAgentProducer.java:
##########
@@ -141,14 +147,49 @@ public void process(Exchange exchange) throws Exception {
         AiAgentBody<?> aiAgentBody = 
exchange.getMessage().getMandatoryBody(AiAgentBody.class);
 
         ToolProvider toolProvider = createComposedToolProvider(tags, exchange);
-        Result<String> result = agent.chat(aiAgentBody, toolProvider);
-        exchange.getMessage().setBody(result.content());
-        populateResultHeaders(result, exchange);
+        Object chatModel = resolveChatModel(agent);
+        GenAiObservationContext observationContext = 
GenAiObservationContext.builder()
+                .operationName(GenAiOperationName.GENERATE_CONTENT)
+                .system(GenAiModelResolver.resolveSystem(chatModel))
+                .requestModel(GenAiModelResolver.resolveModelName(chatModel))
+                .componentScheme("langchain4j-agent")
+                .build();
+        GenAiObservation observation = GenAiObservability.start(exchange, 
observationContext);
+        try {
+            Result<String> result = agent.chat(aiAgentBody, toolProvider);
+            exchange.getMessage().setBody(result.content());
+            populateResultHeaders(result, exchange, 
observationContext.requestModel());
+            observation.recordSuccess(GenAiUsage.of(
+                    result.tokenUsage() != null ? 
result.tokenUsage().inputTokenCount() : null,
+                    result.tokenUsage() != null ? 
result.tokenUsage().outputTokenCount() : null,
+                    result.finishReason(),
+                    observationContext.requestModel()));
+        } catch (RuntimeException e) {
+            observation.recordError(e);
+            throw e;
+        } finally {
+            observation.close();
+        }
+    }
+
+    private Object resolveChatModel(Agent agent) {
+        if (endpoint.getConfiguration().getAgentConfiguration() != null) {

Review Comment:
   **[Medium]** `RESPONSE_MODEL` is set to `requestModel` here, making it 
identical to `REQUEST_MODEL`. The actual response model may differ (e.g., 
`gpt-4o` request resolves to `gpt-4o-2024-11-20`). Since `Result<String>` 
doesn't expose the response model, consider omitting the `RESPONSE_MODEL` 
header rather than reporting a potentially incorrect value.
   
   Same concern applies to the `GenAiUsage` on line 168 where 
`observationContext.requestModel()` is passed as the response model for the 
span attribute.



##########
components/camel-ai/camel-langchain4j-embeddings/src/main/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsProducer.java:
##########
@@ -38,8 +44,35 @@ public LangChain4jEmbeddingsEndpoint getEndpoint() {
     public void process(Exchange exchange) throws Exception {
         final TextSegment in = 
exchange.getMessage().getMandatoryBody(TextSegment.class);
         final EmbeddingModel model = 
getEndpoint().getConfiguration().getEmbeddingModel();
-        final Response<Embedding> result = model.embed(in);
-        final Message message = exchange.getMessage();
+        GenAiObservationContext observationContext = 
GenAiObservationContext.builder()
+                .operationName(GenAiOperationName.EMBEDDINGS)
+                .system(GenAiModelResolver.resolveSystem(model))
+                .requestModel(GenAiModelResolver.resolveModelName(model))
+                .componentScheme("langchain4j-embeddings")
+                .build();
+        GenAiObservation observation = GenAiObservability.start(exchange, 
observationContext);
+        try {
+            final Response<Embedding> result = model.embed(in);
+            populateHeaders(exchange.getMessage(), result, in, 
observationContext.requestModel());
+            observation.recordSuccess(GenAiUsage.of(
+                    result.tokenUsage() != null ? 
result.tokenUsage().inputTokenCount() : null,
+                    result.tokenUsage() != null ? 
result.tokenUsage().outputTokenCount() : null,
+                    result.finishReason(),
+                    observationContext.requestModel()));
+        } catch (RuntimeException e) {
+            observation.recordError(e);

Review Comment:
   **[Medium]** Same issue as the agent producer: `RESPONSE_MODEL` is set to 
`requestModel`. For embeddings, the `Response<Embedding>` object also doesn't 
carry a response model name. Consider omitting `RESPONSE_MODEL` when the actual 
value is unavailable.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to