-
Notifications
You must be signed in to change notification settings - Fork 151
Provide basic AI examples #294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jeremiaswerner
wants to merge
3
commits into
IBM:main
Choose a base branch
from
jeremiaswerner:initial_ai_samples
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #INFERENCE_BASE_URL=http://0.0.0.0:11434/v1 | ||
| #INFERENCE_API_KEY="dummy" | ||
| #INFERENCE_MODEL_NAME="openai/qwen3:4b" | ||
|
|
||
| #INFERENCE_BASE_URL=https://api.perplexity.ai/v1 | ||
| #INFERENCE_API_KEY="REDACTED" | ||
| #INFERENCE_MODEL_NAME="perplexity/sonar-pro" | ||
|
|
||
| INFERENCE_BASE_URL=https://eu-de.ml.cloud.ibm.com | ||
| INFERENCE_API_KEY="REDACTED" | ||
| INFERENCE_MODEL_NAME="watsonx/meta-llama/llama-3-3-70b-instruct" | ||
| INFERENCE_PROJECT_ID="REDACTED" | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| .env |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,95 @@ | ||||||||
| Agent Overview | ||||||||
| -------------- | ||||||||
|
|
||||||||
| An agent is a small, purpose-built service that performs autonomous tasks by combining conversational logic, tool wrappers, and connectors to external services. Agents typically: | ||||||||
|
|
||||||||
| - **Purpose**: Automate workflows and respond to user inputs or events. | ||||||||
| - **Components**: Orchestration logic, task definitions, tool adapters (APIs, search, databases), and an optional lightweight UI. | ||||||||
|
|
||||||||
|  | ||||||||
|
|
||||||||
| Why IBM Cloud Code Engine | ||||||||
| -------------- | ||||||||
|
|
||||||||
| [IBM Cloud Code Engine](https://www.ibm.com/products/code-engine) is a great fit for containerized agents because it provides: | ||||||||
|
|
||||||||
| - **Serverless containers**: Deploy container images without managing infrastructure. | ||||||||
| - **Automatic scaling**: Scale to zero when idle and scale up on demand. | ||||||||
| - **Pay-per-use pricing**: Cost-efficient for intermittent workloads common to agents. | ||||||||
| - **Simple deployment**: Integrates with container registries and CI/CD pipelines. | ||||||||
| - **Managed endpoint**: Provides a secure http endpoint with a managed certificate. | ||||||||
|
|
||||||||
| A very simple Agent | ||||||||
| -------------- | ||||||||
|
|
||||||||
|
|
||||||||
| The agent implementation in this folder demonstrates a compact, production-minded agent pattern. It contains orchestration, task definitions, and tool wrappers that together implement a conversational assistant with tooling capabilities (search, task execution, and basic web UI). | ||||||||
|
|
||||||||
| - **Agent entrypoint**: [./src/main.py](./src/main.py) — starts the agent process and HTTP endpoints. | ||||||||
| - **Agent orchestration**: [./src/agents.py](./src/agents.py) — coordinates agent behavior and message routing. | ||||||||
| - **Tasks**: [./src/tasks.py](./src/tasks.py) — concrete task implementations the agent can run. | ||||||||
| - **Tools / adapters**: [./src/tools.py](./src/tools.py) — wrappers for external APIs or search capabilities. | ||||||||
| - **Utilities**: [./src/utils.py](./src/utils.py) — helpers and common utilities. | ||||||||
| - **Frontend**: [./src/frontend/landing_page.py](./src/frontend/landing_page.py) — lightweight landing page for human interaction (optional). | ||||||||
| - **Example payload**: [./payload/payload.json](./agent/payload/payload.json) — sample input the agent can accept. | ||||||||
|
|
||||||||
| Conceptually this agent acts like a Crew AI / ACP-style assistant: it receives a payload, enriches context (via tools/search), executes defined tasks, and returns results. The implementation is intentionally modular so you can swap tool implementations or extend task behaviors. | ||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
| Deploy the Agent to IBM Cloud Code Engine | ||||||||
| -------------- | ||||||||
|
|
||||||||
| **Prerequisites** | ||||||||
|
|
||||||||
| The Agent requires an nferencing backend (an LLM or similar service) to operate. Configure the backend endpoint and credentials via environment variables. Configure any OpenAI compatible API endpoint such as [OpenAI](https://platform.openai.com/) or [IBM watsonx.ai](https://www.ibm.com/products/watsonx-ai) | ||||||||
|
|
||||||||
| Copy the template | ||||||||
| ```bash | ||||||||
| # If you have a .env.template | ||||||||
| cp .env.template .env | ||||||||
|
Comment on lines
+50
to
+51
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| ``` | ||||||||
| Edit the parameter | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| ```bash | ||||||||
| INFERENCE_BASE_URL=https://eu-de.ml.cloud.ibm.com | ||||||||
| INFERENCE_API_KEY="<YOUR API KEY>" | ||||||||
| INFERENCE_MODEL_NAME="watsonx/meta-llama/llama-3-3-70b-instruct" | ||||||||
| INFERENCE_PROJECT_ID="<YOUR PROJECT>" | ||||||||
| ``` | ||||||||
|
|
||||||||
| **Deploy** | ||||||||
|
|
||||||||
| 1. Log in to IBM Cloud (choose the method that fits your account): | ||||||||
|
|
||||||||
| ```bash | ||||||||
| # Single-sign-on login (interactive) | ||||||||
| ibmcloud login --sso | ||||||||
|
|
||||||||
| # Or with API key (non-interactive): | ||||||||
| ibmcloud login --apikey "$IBMCLOUD_APIKEY" -r REGION -g RESOURCE_GROUP | ||||||||
| ``` | ||||||||
|
|
||||||||
| 2. Change into the agent folder and run the provided deploy script: | ||||||||
|
|
||||||||
| ```bash | ||||||||
| NAME_PREFIX=ce-agent REGION=eu-de ./deploy.sh | ||||||||
| ``` | ||||||||
|
|
||||||||
| 3. The [deploy script](./agent/deploy.sh) builds and/or pushes the container and deploys it to IBM Cloud Code Engine. | ||||||||
|
|
||||||||
|
|
||||||||
| 4. Follow the script output for the agents URL and an example http request. | ||||||||
|
|
||||||||
|
|
||||||||
| What's next | ||||||||
| --------- | ||||||||
|
|
||||||||
| - Modify the tasks in [./src/tasks.py](./src/tasks.py) and register them with the orchestration logic in [./src/agents.py](./src/agents.py). | ||||||||
| - Add your own tools by editing [./src/tools.py](./src/tools.py). | ||||||||
| - Deploy another agent and add it to the Crew [./src/main.py](./src/main.py) | ||||||||
| - [Deploy a MCP Server](../mcp_server_fastmcp/README.md) and make it accessible to your agent(s) | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| Follow the [IBM Cloud Code Engine documentation](https://cloud.ibm.com/docs/codeengine?topic=codeengine-getting-started) to learn about more features and functions. | ||||||||
|
|
||||||||
|  | ||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| #!/bin/bash | ||
|
|
||
| # ============================== | ||
| # ENVIRONMENT SETUP | ||
| # ============================== | ||
|
|
||
| source .env | ||
|
|
||
| REGION="${REGION:=eu-de}" | ||
| NAME_PREFIX="${NAME_PREFIX:=ce-agent}" | ||
|
|
||
| ce_project_name=${PROJECT_NAME:-${NAME_PREFIX}-project} | ||
| resource_group_name=${NAME_PREFIX}-rg | ||
|
|
||
| # ============================== | ||
| # COMMON FUNCTIONS | ||
| # ============================== | ||
|
|
||
| SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) | ||
| source "${SCRIPT_DIR}/../common.sh" | ||
|
|
||
| # Clean up previous run | ||
| function clean() { | ||
| ( | ||
| ibmcloud ce project select --name ${ce_project_name} --quiet 2>/dev/null | ||
| if [ $? == 0 ]; then | ||
| ibmcloud ce project delete --name ${ce_project_name} --force --hard --no-wait 2>/dev/null | ||
| fi | ||
|
|
||
| ibmcloud resource group $resource_group_name --quiet 2>/dev/null | ||
| if [[ $? == 0 ]]; then | ||
| COUNTER=0 | ||
| # some resources (e.g. boot volumes) are deleted with some delay. Hence, the script waits before exiting with an error | ||
| while (( "$(ibmcloud resource service-instances --type all -g $resource_group_name --location $REGION --output json | jq -r '. | length')" > 0 )); do | ||
| sleep 5 | ||
| COUNTER=$((COUNTER + 1)) | ||
| if ((COUNTER > 3)); then | ||
| print_error "Cleanup failed! Please make sure to delete remaining resources manually to avoid unwanted charges." | ||
| ibmcloud resource service-instances --type all -g $resource_group_name --location $REGION | ||
| exit 1 | ||
| fi | ||
| done | ||
| fi | ||
|
|
||
| ibmcloud resource group-delete $resource_group_name --force 2>/dev/null | ||
| ) | ||
| } | ||
|
|
||
| if [[ "$1" == "clean" ]]; then | ||
| print_msg "\nCleaning up the created IBM Cloud resources ..." | ||
| clean | ||
| print_success "\n==========================================\n DONE\n==========================================\n" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # ============================== | ||
| # MAIN SCRIPT FLOW | ||
| # ============================== | ||
|
|
||
| # Ensure that latest versions of used IBM Cloud ClI is installed | ||
| print_msg "\nPulling latest IBM Cloud CLI release ..." | ||
| ibmcloud update --force | ||
|
|
||
| # Ensure that latest versions of used IBM Cloud CLI plugins are installed | ||
| print_msg "\nInstalling required IBM Cloud CLI plugins ..." | ||
| ensure_plugin_is_up_to_date code-engine | ||
|
|
||
| print_msg "\n======================================================" | ||
| print_msg " Setting up \"Code Engine AI Agent\" sample" | ||
| print_msg "======================================================\n" | ||
|
|
||
| target_region $REGION | ||
|
|
||
| # | ||
| # Create the resource group, if it does not exist | ||
| ibmcloud resource group $resource_group_name --quiet | ||
| if [ $? != 0 ]; then | ||
| print_msg "\nCreating resource group '$resource_group_name' ..." | ||
| ibmcloud resource group-create $resource_group_name | ||
| fi | ||
| target_resource_group $resource_group_name | ||
|
|
||
| if ! does_instance_exist codeengine "$ce_project_name"; then | ||
| print_msg "\nCreating the Code Engine project '$ce_project_name' ..." | ||
| ibmcloud ce project create --name $ce_project_name | ||
| if [ $? -ne 0 ]; then | ||
| print_error "Code Engine project creation failed!" | ||
| abortScript | ||
| fi | ||
| else | ||
| print_msg "\nSelecting the Code Engine project '$ce_project_name' ..." | ||
| ibmcloud ce project select --name $ce_project_name | ||
| fi | ||
| project_guid=$(ibmcloud ce project get --name $ce_project_name --output json | jq -r '.guid') | ||
|
|
||
| print_msg "\nCreating code engine secret for the agents with parameters from .env file" | ||
| ibmcloud ce secret create --name agent-secret --from-literal INFERENCE_BASE_URL="$INFERENCE_BASE_URL" \ | ||
| --from-literal INFERENCE_API_KEY="$INFERENCE_API_KEY" \ | ||
| --from-literal INFERENCE_MODEL_NAME="$INFERENCE_MODEL_NAME" \ | ||
| --from-literal INFERENCE_PROJECT_ID="$INFERENCE_PROJECT_ID" | ||
|
|
||
| print_msg "\nCreating the agent as a code engine application" | ||
| ibmcloud ce app create --name agent --env-from-secret agent-secret --build-source ./src --build-strategy dockerfile --cpu 1 --memory 4G -p 8080 --wait-timeout 600 --min-scale 0 --visibility public | ||
|
|
||
| while true; do | ||
| ibmcloud ce app list | ||
| not_ready_apps=$(ibmcloud ce app list | grep -e "agent" | grep "Not Ready") | ||
| if [ "$not_ready_apps" == "" ]; then | ||
| break # all apps are ready | ||
| fi | ||
| print_msg "\nWaiting for all applications to be ready (sleep 15s)..." | ||
| sleep 15 | ||
| done | ||
|
|
||
| print_msg "\n" | ||
| print_msg "\nAgent application is ready." | ||
| print_msg "\n" | ||
|
|
||
| url=$(ibmcloud ce app get --name agent -o json | jq -r '.status.url') | ||
| print_msg "\nAgent is reachable under the following url:" | ||
| echo $url | ||
|
|
||
| print_msg "\n" | ||
| print_msg "\nList the agents:" | ||
| curl -s -X GET $url/agents | jq | ||
|
|
||
|
|
||
| print_msg "\n" | ||
| print_msg "\nCalling the agent with the following payload" | ||
| cat payload/payload.json | jq | ||
|
|
||
| curl -s -X POST $url/runs -H "Content-Type: application/json" -d @payload/payload.json | jq | ||
|
|
||
| print_success "\n==========================================" | ||
| print_success " SUCCESS" | ||
| print_success "==========================================\n" | ||
| print_msg "\n" | ||
| print_msg "\nrun ./deploy.sh clean to remove all created resources" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {"agent_name": "City_Expert", "input": [{"role": "User", "parts": [{"content": "{\"city\": \"Stuttgart\", \"country\": \"Germany\", \"currency\": \"EUR\"}"}]}]} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| __pycache__/ | ||
| .my_cache_dir | ||
| .pytest_cache | ||
| .ruff_cache | ||
| *.pyc | ||
| *.pyo | ||
| *.pyd | ||
| *.db | ||
| *.sqlite3 | ||
|
|
||
| .env | ||
| .venv | ||
| *.env | ||
|
|
||
| **/.env | ||
| **/.venv | ||
| **/*.env | ||
|
|
||
| .git | ||
| .gitignore | ||
| Dockerfile | ||
| .dockerignore | ||
|
|
||
| *.log | ||
| *.bak | ||
| *.swp | ||
|
|
||
| .vscode/ | ||
| .idea/ | ||
|
|
||
| # OS-specific | ||
| .DS_Store | ||
| Thumbs.db |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # Python-generated files | ||
| __pycache__/ | ||
| *.py[oc] | ||
| build/ | ||
| dist/ | ||
| wheels/ | ||
| *.egg-info | ||
| .mypy_cache | ||
| .coverage | ||
| .python-version | ||
|
|
||
| # Virtual environments | ||
| .venv |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| ################################################# | ||
| # Build stage | ||
| ################################################# | ||
|
|
||
| FROM registry.access.redhat.com/ubi9/python-312:latest AS build-stage | ||
|
|
||
| USER 1001 | ||
| WORKDIR $HOME | ||
|
|
||
| ENV PATH="$HOME/.venv/bin:$PATH" | ||
|
|
||
| # Install uv. | ||
| COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ | ||
|
|
||
| # Copy the application into the container. | ||
| COPY . . | ||
|
|
||
| # Install the application dependencies. | ||
| RUN uv sync --frozen --no-cache | ||
|
|
||
| USER root | ||
|
|
||
| # https://docs.trychroma.com/updates/troubleshooting#sqlite | ||
| RUN uv add pysqlite3-binary | ||
| RUN sed -i '1i # ruff: noqa: E402,I001\n__import__("pysqlite3")\nimport sys\nsys.modules["sqlite3"] = sys.modules.pop("pysqlite3")' main.py | ||
|
|
||
| # Linting | ||
| RUN ruff check . --no-cache | ||
|
|
||
| # Reinstall without dev dependencies | ||
| RUN uv sync --frozen --no-dev | ||
|
|
||
| USER 1001 | ||
|
|
||
| ################################################# | ||
| # Production stage | ||
| ################################################# | ||
|
|
||
| FROM registry.access.redhat.com/ubi9/python-312:latest | ||
|
|
||
| USER 1001 | ||
| WORKDIR $HOME | ||
|
|
||
| ENV PATH="$HOME/.venv/bin:$PATH" | ||
| ENV MODE=${MODE:-production} | ||
| ENV LOG_LEVEL=${LOG_LEVEL:-DEBUG} | ||
| ENV PORT=${PORT:-5630} | ||
| ENV WORKERS=${WORKERS:-1} | ||
|
|
||
| COPY --from=build-stage $HOME/ . | ||
|
|
||
| # Run the application. | ||
| CMD uvicorn main:app --host 0.0.0.0 --port ${PORT} --workers ${WORKERS} --log-level ${LOG_LEVEL,,} --timeout-keep-alive 50 --header server:acp |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # City Expert Agent | ||
|
|
||
| ```sh | ||
| source .venv/bin/activate | ||
| ``` | ||
|
|
||
| ```sh | ||
| uv run main.py | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import os | ||
|
|
||
| from crewai import LLM, Agent | ||
| from dotenv import load_dotenv | ||
|
|
||
| from tools import duckduckgosearch_tool, scrape_tool | ||
|
|
||
| load_dotenv() | ||
|
|
||
| llm = LLM( | ||
| model=os.getenv("INFERENCE_MODEL_NAME"), | ||
| base_url=os.getenv("INFERENCE_BASE_URL"), | ||
| api_key=os.getenv("INFERENCE_API_KEY", ""), | ||
| project_id=os.getenv("INFERENCE_PROJECT_ID"), | ||
| max_tokens=8192, | ||
| temperature=0, | ||
| ) | ||
|
|
||
| city_local_expert_agent = Agent( | ||
| role="Local City Expert", | ||
| goal="Provide the BEST insights about the selected city", | ||
| backstory="A knowledgeable local guide with extensive information about the city, it's attractions and customs", | ||
| tools=[ | ||
| scrape_tool, | ||
| duckduckgosearch_tool, | ||
| ], | ||
| reasoning=True, | ||
| verbose=True, | ||
| llm=llm, | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.