diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/GenAiObservabilityRoute.java b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/GenAiObservabilityRoute.java new file mode 100644 index 0000000000000..9bbbd1cdaa9b9 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/GenAiObservabilityRoute.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import dev.langchain4j.model.chat.ChatModel; +import dev.langchain4j.model.ollama.OllamaChatModel; + +import org.apache.camel.builder.RouteBuilder; + +import static java.time.Duration.ofSeconds; + +/** + * Minimal GenAI route for observing LLM calls with Camel 4.23+. + *

+ * Requires Ollama running locally (see README.md). + */ +public class GenAiObservabilityRoute extends RouteBuilder { + + @Override + public void configure() { + ChatModel chatModel = OllamaChatModel.builder() + .baseUrl("{{ollama.baseUrl:http://localhost:11434}}") + .modelName("{{ollama.model:llama3.2}}") + .temperature(0.2) + .timeout(ofSeconds(120)) + .build(); + getContext().getRegistry().bind("chatModel", chatModel); + + from("timer:genai?period={{genai.period:15000}}") + .routeId("genai-chat") + .setBody(constant("In one sentence, what is Apache Camel integration?")) + .to("langchain4j-chat:demo?chatModel=#chatModel") + .log("LLM reply: ${body}") + .log("Request model: ${header.CamelLangChain4jChatRequestModel}") + .log("Response model: ${header.CamelLangChain4jChatResponseModel}"); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/README.md b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/README.md new file mode 100644 index 0000000000000..da9ae019dd09f --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/README.md @@ -0,0 +1,80 @@ +## GenAI Observability (JBang / CLI / TUI) + +This example demonstrates **GenAI observability** in Apache Camel 4.23+: OpenTelemetry +`gen_ai.*` span attributes and Micrometer metrics for `langchain4j-chat` LLM calls. + +A timer route sends a prompt to Ollama via LangChain4j every 15 seconds. With +`--observe`, Camel exposes health/metrics/tracing and the TUI can show GenAI spans +and token usage. + +Blog post: see `docs/blog-drafts/genai-observability-01-jbang-cli-tui.adoc` in the Camel source tree. + +### Prerequisites + +- [Camel JBang](https://camel.apache.org/manual/camel-jbang-jdk-installation.html) (Camel 4.23+) +- [Ollama](https://ollama.com/) running locally + +```sh +ollama pull llama3.2 +ollama serve +``` + +### How to run + +From this directory: + +```sh +camel run GenAiObservabilityRoute.java application.properties --observe \ + --dependency=camel-langchain4j-chat \ + --dependency=camel-ai-observability \ + --dependency=langchain4j-ollama +``` + +### Verify GenAI observability + +**Metrics** (Prometheus format): + +```sh +curl -s http://127.0.0.1:9876/observe/metrics | grep gen_ai +``` + +Look for `gen_ai_client_operation` and `gen_ai_client_token_usage`. + +**TUI — Spans tab** + +In another terminal: + +```sh +camel tui +``` + +Select the running integration, open the **Spans** tab, and trigger a timer tick. +Each LLM call creates a child span with `gen_ai.operation.name=chat`, +`gen_ai.request.model`, and token usage attributes. + +**TUI — AI usage (Ctrl+U)** + +With the AI panel open, press **Ctrl+U** to see combined token usage from +`camel ask` and route-level GenAI spans (Camel 4.23 Phase 2). + +**Ask about your integration** + +```sh +camel ask "Which routes call an LLM and what model do they use?" +``` + +### Disable GenAI observability + +```properties +camel.ai.observability.enabled=false +``` + +### Help and contributions + +If you hit any problem using Camel or have some feedback, then please +[let us know](https://camel.apache.org/community/support/). + +We also love contributors, so +[get involved](https://camel.apache.org/community/contributing/) :-) + +The Camel riders! diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/application.properties b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/application.properties new file mode 100644 index 0000000000000..1aa678ee00562 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/ai/genai-observability/application.properties @@ -0,0 +1,7 @@ +# Ollama connection (start Ollama and pull the model first: ollama pull llama3.2) +ollama.baseUrl=http://localhost:11434 +ollama.model=llama3.2 +genai.period=15000 + +# GenAI observability (Camel 4.23+) — enabled by default when observability backends are present +camel.ai.observability.enabled=true diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json index bd1affbb688b0..91d01bd4efc01 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json @@ -73,6 +73,31 @@ "pii.schema.json" ] }, + { + "name": "ai/genai-observability", + "title": "GenAI Observability", + "description": "Observe LangChain4j LLM calls with OpenTelemetry gen_ai spans, Micrometer metrics, and the Camel TUI", + "level": "intermediate", + "tags": [ + "ai", + "observability", + "langchain4j", + "opentelemetry", + "genai", + "tui" + ], + "bundled": true, + "requiresDocker": false, + "hasCitrusTests": false, + "files": [ + "README.md", + "application.properties", + "GenAiObservabilityRoute.java" + ], + "infraServices": [ + "ollama" + ] + }, { "name": "ai/smart-log-analyzer", "title": "Smart Log Analyzer",