diff --git a/ai/langchain-skills-agent/.env.sample b/ai/langchain-skills-agent/.env.sample index 7b4b2c7dc..96317dc06 100644 --- a/ai/langchain-skills-agent/.env.sample +++ b/ai/langchain-skills-agent/.env.sample @@ -1,14 +1,39 @@ -# LLM Configuration (OpenAI-compatible API) -# Configure your inference backend here +# ============================== +# LLM Configuration (RedHat AI Inference Service) +# ============================== +# Get your API key from: https://cloud.ibm.com/inference/overview -# IBM watsonx.ai -INFERENCE_BASE_URL=https://eu-de.ml.cloud.ibm.com -INFERENCE_API_KEY="YOUR_API_KEY" -INFERENCE_MODEL_NAME="meta-llama/llama-3-2-11b-vision-instruct" -INFERENCE_PROJECT_ID="YOUR_PROJECT_ID" +# RedHat AI Inference Service endpoint +INFERENCE_BASE_URL=https://us-east.rhai.ibm.com/v1/projects/YOUR_PROJECT_ID/inference +# IBM Cloud API Key for authentication +IBM_CLOUD_API_KEY=YOUR_IBM_CLOUD_API_KEY +# Model to use (e.g., llama-3-3-70b-instruct, granite-3-8b-instruct) +INFERENCE_MODEL_NAME=llama-3-3-70b-instruct + +# ============================== +# External API Keys (Optional) +# ============================== +# These are optional - the agent will work without them but with limited functionality + +# OpenWeather API Key (for weather forecasts) +# Get your key from: https://openweathermap.org/api +OPENWEATHER_API_KEY=YOUR_OPENWEATHER_API_KEY + +# Exchange Rate API Key (for currency conversion) +# Get your key from: https://www.exchangerate-api.com/ +EXCHANGE_RATE_API_KEY=YOUR_EXCHANGE_RATE_API_KEY + +# ============================== # IBM Cloud Configuration (for deployment) +# ============================== + +# IBM Cloud region (e.g., eu-de, us-south, us-east) REGION=eu-de + +# Code Engine project name PROJECT_NAME=langchain-skills-agent-project + +# Resource name prefix NAME_PREFIX=ce-langchain-agent \ No newline at end of file diff --git a/ai/langchain-skills-agent/DEPLOYMENT.md b/ai/langchain-skills-agent/DEPLOYMENT.md new file mode 100644 index 000000000..4fdb73fd4 --- /dev/null +++ b/ai/langchain-skills-agent/DEPLOYMENT.md @@ -0,0 +1,323 @@ +# Deployment Guide - LangChain Skills Agent on IBM Cloud Code Engine + +This guide walks you through deploying the LangChain Skills Agent to IBM Cloud Code Engine using the Dockerfile strategy. + +## ๐ Prerequisites + +### 1. IBM Cloud Account +- Sign up at [IBM Cloud](https://cloud.ibm.com) +- Ensure you have access to Code Engine service + +### 2. RedHat AI Inference Service +- Access the [RedHat AI Inference Service](https://cloud.ibm.com/inference/overview) +- Create a project and note your project ID +- Generate an IBM Cloud API key + +### 3. IBM Cloud CLI +Install the IBM Cloud CLI: +```bash +curl -fsSL https://clis.cloud.ibm.com/install/linux | sh +``` + +Install the Code Engine plugin: +```bash +ibmcloud plugin install code-engine +``` + +### 4. Optional API Keys +For full functionality, obtain: +- **OpenWeather API Key**: [https://openweathermap.org/api](https://openweathermap.org/api) +- **Exchange Rate API Key**: [https://www.exchangerate-api.com/](https://www.exchangerate-api.com/) + +## ๐ง Configuration + +### Step 1: Configure Environment Variables + +1. Copy the sample environment file: + ```bash + cp .env.sample .env + ``` + +2. Edit `.env` with your credentials: + ```bash + # RedHat AI Inference Service + INFERENCE_BASE_URL=https://us-east.rhai.ibm.com/v1/projects/YOUR_PROJECT_ID/inference + IBM_CLOUD_API_KEY=YOUR_IBM_CLOUD_API_KEY + INFERENCE_MODEL_NAME=llama-3-3-70b-instruct + + # Optional API Keys + OPENWEATHER_API_KEY=YOUR_OPENWEATHER_API_KEY + EXCHANGE_RATE_API_KEY=YOUR_EXCHANGE_RATE_API_KEY + + # IBM Cloud Configuration + REGION=eu-de + PROJECT_NAME=langchain-skills-agent-project + NAME_PREFIX=ce-langchain-agent + ``` + +### Step 2: Authenticate to IBM Cloud + +Choose one of the following methods: + +**Option A: SSO Authentication** +```bash +ibmcloud login --sso +``` + +**Option B: API Key Authentication** +```bash +ibmcloud login --apikey YOUR_IBM_CLOUD_API_KEY +``` + +## ๐ Deployment + +### Automated Deployment + +The `deploy.sh` script handles the complete deployment process: + +```bash +./deploy.sh +``` + +This script will: +1. โ Update IBM Cloud CLI and plugins +2. โ Create a resource group (if needed) +3. โ Create a Code Engine project +4. โ Create a secret with your environment variables +5. โ Build the Docker image using the Dockerfile +6. โ Deploy the application with optimal configuration +7. โ Configure health checks and auto-scaling +8. โ Provide the application URL + +### What the Deployment Includes + +**Application Configuration:** +- **Build Strategy**: Dockerfile (multi-stage build for optimization) +- **CPU**: 1 vCPU +- **Memory**: 4GB +- **Port**: 8080 +- **Min Scale**: 1 instance (always available) +- **Max Scale**: 10 instances (auto-scales based on load) +- **Health Check**: `/health` endpoint with 30s initial delay +- **Visibility**: Public (accessible via HTTPS) + +**Security:** +- All sensitive credentials stored in Code Engine secrets +- HTTPS endpoint with managed certificate +- Non-root container user (UID 1001) +- Minimal base image (UBI Python) + +## ๐ Monitoring Deployment + +### Check Application Status +```bash +ibmcloud ce application get --name langchain-agent +``` + +### View Application Logs +```bash +ibmcloud ce application logs --name langchain-agent --tail 100 +``` + +### Follow Logs in Real-time +```bash +ibmcloud ce application logs --name langchain-agent --follow +``` + +### Check Application Events +```bash +ibmcloud ce application events --name langchain-agent +``` + +## ๐งช Testing the Deployment + +### 1. Access the Landing Page +The deployment script will output the application URL. Open it in your browser: +``` +https://langchain-agent.xxx.codeengine.appdomain.cloud +``` + +### 2. Test the Health Endpoint +```bash +curl https://YOUR_APP_URL/health +``` + +Expected response: +```json +{ + "status": "healthy", + "agent": "Travel_Weather_Assistant", + "skills_loaded": 3 +} +``` + +### 3. Get Agent Information +```bash +curl https://YOUR_APP_URL/info | jq +``` + +### 4. Test the Agent +```bash +curl -X POST https://YOUR_APP_URL/runs \ + -H "Content-Type: application/json" \ + -d @payload/payload.json | jq +``` + +Or use the example from the script output: +```bash +curl -X POST https://YOUR_APP_URL/runs \ + -H "Content-Type: application/json" \ + -d '{ + "agent_name": "Travel_Weather_Assistant", + "input": [{ + "role": "user", + "parts": [{ + "content": "What is the weather in Paris?" + }] + }] + }' | jq +``` + +## ๐ Updating the Application + +### Update Environment Variables +```bash +# Update the secret +ibmcloud ce secret update --name langchain-agent-secret \ + --from-literal IBM_CLOUD_API_KEY="NEW_API_KEY" + +# Restart the application to pick up changes +ibmcloud ce application update --name langchain-agent +``` + +### Update Application Code +```bash +# Rebuild and redeploy +ibmcloud ce application update --name langchain-agent \ + --build-source ./src \ + --strategy dockerfile +``` + +### Scale the Application +```bash +# Adjust scaling parameters +ibmcloud ce application update --name langchain-agent \ + --min-scale 2 \ + --max-scale 20 \ + --concurrency 50 +``` + +### Update Resource Allocation +```bash +# Increase CPU and memory +ibmcloud ce application update --name langchain-agent \ + --cpu 2 \ + --memory 8G +``` + +## ๐งน Cleanup + +To remove all created resources and avoid charges: + +```bash +./deploy.sh clean +``` + +This will delete: +- The Code Engine application +- The Code Engine project +- All secrets and configurations +- The resource group + +## ๐ Troubleshooting + +### Application Not Starting + +**Check logs for errors:** +```bash +ibmcloud ce application logs --name langchain-agent --tail 200 +``` + +**Common issues:** +- Missing environment variables โ Verify secret configuration +- Port mismatch โ Application listens on 8080 +- Memory issues โ Increase memory allocation + +### Build Failures + +**Check build logs:** +```bash +ibmcloud ce buildrun logs --name langchain-agent-xxxxx +``` + +**Common issues:** +- Dockerfile syntax errors โ Validate Dockerfile +- Dependency installation failures โ Check pyproject.toml +- Network issues โ Retry the build + +### Health Check Failures + +**Verify health endpoint:** +```bash +# Get application URL +APP_URL=$(ibmcloud ce application get --name langchain-agent --output json | jq -r '.status.url') + +# Test health endpoint +curl $APP_URL/health +``` + +**Common issues:** +- Application not listening on 0.0.0.0 โ Check main.py +- Health check timeout too short โ Increase initial delay +- Application startup slow โ Increase probe-live-initial-delay + +### Performance Issues + +**Check current scaling:** +```bash +ibmcloud ce application get --name langchain-agent | grep -A 5 "Scale" +``` + +**Optimize scaling:** +```bash +# Increase max scale for high traffic +ibmcloud ce application update --name langchain-agent --max-scale 20 + +# Keep more instances warm +ibmcloud ce application update --name langchain-agent --min-scale 2 + +# Adjust concurrency +ibmcloud ce application update --name langchain-agent --concurrency 50 +``` + +## ๐ Additional Resources + +- [IBM Cloud Code Engine Documentation](https://cloud.ibm.com/docs/codeengine) +- [RedHat AI Inference Service](https://cloud.ibm.com/inference/overview) +- [Code Engine CLI Reference](https://cloud.ibm.com/docs/codeengine?topic=codeengine-cli) +- [LangChain Documentation](https://python.langchain.com/) + +## ๐ Security Best Practices + +1. **Never commit `.env` file** - It contains sensitive credentials +2. **Use Code Engine secrets** - All credentials are stored securely +3. **Rotate API keys regularly** - Update secrets when keys change +4. **Monitor access logs** - Review application logs for suspicious activity +5. **Use HTTPS only** - Code Engine provides managed certificates +6. **Implement authentication** - Add authentication for production use + +## ๐ก Next Steps + +After successful deployment: + +1. **Add Custom Domain**: Configure a custom domain for your application +2. **Set Up Monitoring**: Use IBM Cloud Monitoring for observability +3. **Configure Alerts**: Set up alerts for application health +4. **Implement Rate Limiting**: Protect against abuse +5. **Add Authentication**: Secure your endpoints with OAuth or API keys +6. **Scale Testing**: Test auto-scaling behavior under load +7. **Cost Optimization**: Monitor usage and adjust scaling parameters + +--- + +**Need Help?** Check the [main README](README.md) or open an issue on GitHub. \ No newline at end of file diff --git a/ai/langchain-skills-agent/README.md b/ai/langchain-skills-agent/README.md index ea3d3d76e..3742ac9e8 100644 --- a/ai/langchain-skills-agent/README.md +++ b/ai/langchain-skills-agent/README.md @@ -1,6 +1,6 @@ # LangChain Skills Agent on Code Engine -A modular, skill-based agent built with LangChain that demonstrates a clean architecture for organizing agent capabilities. This agent provides weather forecasting, travel recommendations, and currency conversion through a dynamic skill loading system. +A modular, skill-based agent built with LangChain that demonstrates a clean architecture for organizing agent capabilities. This agent runs a **full agentic loop**, autonomously calling tools and processing results until it can provide a complete answer. It provides weather forecasting, travel recommendations, and currency conversion through a dynamic skill loading system. ## Why IBM Cloud Code Engine @@ -12,6 +12,18 @@ A modular, skill-based agent built with LangChain that demonstrates a clean arch - **Simple deployment**: Integrates with container registries and CI/CD pipelines. - **Managed endpoint**: Provides a secure http endpoint with a managed certificate. +## Why RedHat AI Inference Service + +This agent uses the [RedHat AI Inference Service](https://cloud.ibm.com/inference/overview) for its LLM capabilities, offering: + +- **Production-ready frontier AI models**: Access to state-of-the-art models like Llama 3.3 70B +- **No operational overhead**: Fully managed service with no infrastructure to maintain +- **Built-in enterprise security**: Enterprise-grade security and compliance out of the box +- **Cost controls**: Token-based consumption pricing with no standing costs - you only pay for what you use +- **Zero infrastructure management**: No servers to provision, scale, or maintain + +The token-based consumption model means you're never paying for idle capacity, making it perfect for agent workloads that scale dynamically. + ## The architecture  @@ -24,12 +36,71 @@ This agent showcases a **skill-based setup** where each capability is: - Implemented as a LangChain tool - Dynamically discovered and loaded at runtime + + +### Agentic Loop + +The agent runs a **full agentic loop** that autonomously: +1. Receives a user query +2. Analyzes what information is needed +3. Calls appropriate tools (weather, travel, currency conversion) +4. Processes tool results +5. Decides if more information is needed +6. Repeats steps 3-5 until it has everything needed +7. Synthesizes a comprehensive response + +This means the agent can handle complex, multi-step queries without requiring step-by-step user guidance. + +**Example Agentic Loop Output:** + +``` +User Query: "Plan a trip to Paris for 5 days with a budget of $2000" + +๐ AGENT ITERATION 1/10 +๐ค CALLING INFERENCE SERVICE +โ INFERENCE SERVICE RESPONSE RECEIVED +๐ง EXECUTING 2 TOOL CALL(S) + ๐ Tool Call 1/2 + Name: weather_forecast + Arguments: {'location': 'Paris', 'days': 5} + โ Success: Paris will have partly cloudy weather for the next 5 days... + ๐ Tool Call 2/2 + Name: currency_converter + Arguments: {'amount': 2000, 'from_currency': 'USD', 'to_currency': 'EUR'} + โ Success: 2000 USD = 1850.00 EUR + +๐ AGENT ITERATION 2/10 +๐ค CALLING INFERENCE SERVICE +โ INFERENCE SERVICE RESPONSE RECEIVED +๐ง EXECUTING 1 TOOL CALL(S) + ๐ Tool Call 1/1 + Name: travel_recommendations + Arguments: {'destination_type': 'city', 'budget': 'moderate', 'season': 'current'} + โ Success: For Paris with a moderate budget, consider staying in the Marais... + +๐ AGENT ITERATION 3/10 +๐ค CALLING INFERENCE SERVICE +โ INFERENCE SERVICE RESPONSE RECEIVED +โ AGENT LOOP COMPLETE +Total iterations: 3 +๐ค FINAL OUTPUT: Based on the current forecast, Paris will have partly cloudy weather +for the next 5 days with temperatures around 18-22ยฐC. Perfect for sightseeing! + +For your $2,000 budget (approximately โฌ1,850), here's a suggested plan: +- Accommodation: Stay in the Marais district (โฌ120/night = โฌ600 total) +- Daily expenses: โฌ150/day for meals and activities (โฌ750 total) +- Transportation: Paris Visite pass for 5 days (โฌ65) +- Remaining budget: โฌ435 for shopping and extras + +Must-see attractions: Eiffel Tower, Louvre Museum, Notre-Dame, and Montmartre... +``` ### Key Features - **๐ง Modular Skills**: Each skill is independent and easy to add/remove - **๐ Metadata-Driven**: Skills include YAML frontmatter with configuration - **๐ Dynamic Loading**: Skills are automatically discovered from the `skills/` directory +- **๐ค Full Agentic Loop**: Autonomous tool calling and result processing - **๐ Production Ready**: Containerized and deployable to IBM Cloud Code Engine - **๐จ Clean Architecture**: Clear separation of concerns and easy to extend @@ -89,222 +160,74 @@ langchain-skills-agent/ ### Prerequisites -1. **LLM Backend**: Configure an OpenAI-compatible API endpoint - - [IBM watsonx.ai](https://www.ibm.com/products/watsonx-ai) (recommended) +1. **RedHat AI Inference Service**: Get your API key from [IBM Cloud Inference](https://cloud.ibm.com/inference/overview) + - Token-based consumption with no standing costs + - Access to production-ready frontier AI models + - Built-in enterprise security and compliance 2. **IBM Cloud CLI** (for deployment): ```bash curl -fsSL https://clis.cloud.ibm.com/install/linux | sh ``` -## โ๏ธ Deploy to IBM Cloud Code Engine -### Configuration +### Run locally -1. **Copy and configure environment**: +1. Copy the sample environment file and add your credentials: ```bash cp .env.sample .env ``` -2. **Edit `.env`** with your credentials: - ```bash - INFERENCE_BASE_URL=https://eu-de.ml.cloud.ibm.com - INFERENCE_API_KEY="YOUR_API_KEY" - INFERENCE_MODEL_NAME="meta-llama/llama-3-2-11b-vision-instruct" - INFERENCE_PROJECT_ID="YOUR_PROJECT_ID" - ``` - -### Deploy - -1. **Login to IBM Cloud**: +2. Start the app locally from the `src` directory: ```bash - ibmcloud login --sso - # or with API key: - ibmcloud login --apikey "$IBMCLOUD_APIKEY" + cd src + uv run uvicorn main:app --host 0.0.0.0 --port 8080 ``` -2. **Run deployment**: - ```bash - ./deploy.sh +3. Open the dashboard in your browser: + ```text + http://localhost:8080/ ``` -3. **The script will**: - - Create a Code Engine project - - Build and deploy the containerized agent - - Configure secrets from your `.env` file - - Provide the agent URL - -### Cleanup - -Remove all created resources: -```bash -./deploy.sh clean -``` - -### Local Development - -1. **Clone and setup**: - ```bash - cd langchain-skills-agent - cp .env.sample .env - # Edit .env with your API credentials - ``` - -2. **Install dependencies**: - ```bash - cd src - pip install -e . - # or with uv: - uv sync - ``` +## โ๏ธ Deploy to IBM Cloud Code Engine -3. **Run locally**: +1. Authenticate with IBM Cloud: ```bash - python main.py + ibmcloud login --sso ``` - -4. **Test the agent**: + Or use an API key: ```bash - # Visit the landing page - open http://localhost:8080 - - # Or use the API - curl -X POST http://localhost:8080/runs \ - -H "Content-Type: application/json" \ - -d @payload/payload.json + ibmcloud login --apikey YOUR_IBM_CLOUD_API_KEY ``` -## ๐ API Endpoints - -### `GET /` -Landing page with agent information and documentation - -### `GET /agents` -List available agents - -### `POST /runs` -Execute the agent with a query - -**Request:** -```json -{ - "messages": [ - { - "role": "user", - "content": "What's the weather in Paris?" - } - ] -} -``` - -### `GET /info` -Get agent information and loaded skills - -### `GET /health` -Health check endpoint - -## ๐ ๏ธ Adding New Skills - -1. **Create skill directory**: +2. Deploy the application: ```bash - mkdir -p src/skills/my_new_skill - ``` - -2. **Create `skill.md`** with metadata: - ```markdown - --- - name: "My New Skill" - description: "What this skill does" - version: "1.0.0" - category: "utility" - parameters: - - name: input - type: string - required: true - description: "Input parameter" - --- - - # My New Skill - - Detailed documentation here... + ./deploy.sh ``` -3. **Create `__init__.py`** with implementation: - ```python - from langchain.tools import tool - - @tool - def my_new_skill(input: str) -> str: - """Tool description for the LLM.""" - # Implementation here - return result +3. Access the app using the URL printed by the script, for example: + ```text + https://langchain-agent.xxx.codeengine.appdomain.cloud ``` -4. **Restart the agent** - the skill will be automatically discovered! - -## ๐ Skill Metadata Format - -Each `skill.md` file uses YAML frontmatter: - -```yaml ---- -name: "Skill Name" -description: "Brief description" -version: "1.0.0" -category: "category_name" -parameters: - - name: param_name - type: string|integer|float|boolean - required: true|false - default: default_value - description: "Parameter description" ---- -``` - -## ๐ง Configuration - -### Environment Variables - -| Variable | Description | Example | -|----------|-------------|---------| -| `INFERENCE_BASE_URL` | LLM API endpoint | `https://eu-de.ml.cloud.ibm.com` | -| `INFERENCE_API_KEY` | API key for LLM | `your-api-key` | -| `INFERENCE_MODEL_NAME` | Model identifier | `watsonx/meta-llama/llama-3-3-70b-instruct` | -| `INFERENCE_PROJECT_ID` | Project ID (watsonx.ai) | `your-project-id` | -| `OPENWEATHER_API_KEY` | Weather API key (optional) | `your-key` | -| `EXCHANGE_RATE_API_KEY` | Exchange rate API key (optional) | `your-key` | - -## ๐จ Architecture Highlights - -### Dynamic Skill Loading +For the full deployment walkthrough, see [DEPLOYMENT.md](DEPLOYMENT.md). -The `skill_loader.py` module: -1. Scans the `skills/` directory -2. Parses `skill.md` metadata -3. Imports Python modules -4. Registers tools with LangChain -5. Makes them available to the agent + -### LangChain Integration -- Uses `ChatWatxonx` for Watsonx-compatible APIs -- Implements `create_tool_calling_agent` for tool use -- Provides `AgentExecutor` for orchestration -- Supports async operations +## ๐ Next steps -### ACP SDK Integration +- Add and deploy more agents to the same Code Engine project +- Add and deploy [MCP Servers](../mcp-server/README.md) +- Secure the agent endpoint with [OIDC-based authentication](../../auth-oidc-proxy/README.md) -- Compatible with Agent Communication Protocol -- Provides standard agent endpoints -- Supports message-based interaction -- Easy integration with agent platforms ## ๐ Learn More -- [IBM Cloud Code Engine](https://cloud.ibm.com/docs/codeengine) -- [LangChain Documentation](https://python.langchain.com/) -- [IBM watsonx.ai](https://www.ibm.com/products/watsonx-ai) -- [Agent Communication Protocol](https://github.com/IBM/agent-communication-protocol) +- [RedHat AI Inference Service](https://cloud.ibm.com/inference/overview) - Production-ready frontier AI models with no operational overhead +- [IBM Cloud Code Engine](https://cloud.ibm.com/docs/codeengine) - Serverless container platform +- [LangChain Documentation](https://python.langchain.com/) - LangChain framework +- [Agent Communication Protocol](https://github.com/IBM/agent-communication-protocol) - Standard agent protocol --- diff --git a/ai/langchain-skills-agent/deploy.sh b/ai/langchain-skills-agent/deploy.sh index 87edfdc04..dce68d581 100755 --- a/ai/langchain-skills-agent/deploy.sh +++ b/ai/langchain-skills-agent/deploy.sh @@ -96,15 +96,25 @@ fi project_guid=$(ibmcloud ce project get --name $ce_project_name --output json | jq -r '.guid') print_msg "\nCreating code engine secret for the agent with parameters from .env file" -ibmcloud ce secret create --name langchain-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" \ ---from-literal OPENWEATHER_API_KEY="$OPENWEATHER_API_KEY" \ ---from-literal EXCHANGE_RATE_API_KEY="$EXCHANGE_RATE_API_KEY" - -print_msg "\nCreating the LangChain agent as a code engine application" -ibmcloud ce app create --name langchain-agent --env-from-secret langchain-agent-secret --build-source ./src --cpu 1 --memory 4G -p 8080 --wait-timeout 600 --min-scale 1 --visibility public +ibmcloud ce secret create --name langchain-agent-secret \ + --from-literal IBM_CLOUD_API_KEY="$IBM_CLOUD_API_KEY" \ + --from-literal INFERENCE_BASE_URL="$INFERENCE_BASE_URL" \ + --from-literal INFERENCE_MODEL_NAME="$INFERENCE_MODEL_NAME" \ + --from-literal OPENWEATHER_API_KEY="$OPENWEATHER_API_KEY" \ + --from-literal EXCHANGE_RATE_API_KEY="$EXCHANGE_RATE_API_KEY" + +print_msg "\nCreating the LangChain agent as a code engine application using Dockerfile strategy" +ibmcloud ce app create --name langchain-agent \ + --build-source ./src \ + --build-strategy dockerfile \ + --env-from-secret langchain-agent-secret \ + --cpu 1 \ + --memory 4G \ + --port 8080 \ + --min-scale 1 \ + --max-scale 10 \ + --wait-timeout 600 \ + --visibility public while true; do ibmcloud ce app list diff --git a/ai/langchain-skills-agent/images/agent_dashboard.png b/ai/langchain-skills-agent/images/agent_dashboard.png new file mode 100644 index 000000000..6302a4aa2 Binary files /dev/null and b/ai/langchain-skills-agent/images/agent_dashboard.png differ diff --git a/ai/langchain-skills-agent/images/agent_test.png b/ai/langchain-skills-agent/images/agent_test.png new file mode 100644 index 000000000..5d22d8be3 Binary files /dev/null and b/ai/langchain-skills-agent/images/agent_test.png differ diff --git a/ai/langchain-skills-agent/images/architecture.png b/ai/langchain-skills-agent/images/architecture.png index 6962fe1be..2483241d2 100644 Binary files a/ai/langchain-skills-agent/images/architecture.png and b/ai/langchain-skills-agent/images/architecture.png differ diff --git a/ai/langchain-skills-agent/src/Dockerfile b/ai/langchain-skills-agent/src/Dockerfile new file mode 100644 index 000000000..e782e8b7b --- /dev/null +++ b/ai/langchain-skills-agent/src/Dockerfile @@ -0,0 +1,50 @@ +# Use Python 3.13 base image for builder +FROM python:3.13-slim AS builder + +WORKDIR /build + +# Install uv for faster dependency installation +RUN pip install --no-cache-dir uv + +# Copy dependency files +COPY pyproject.toml uv.lock ./ + +# Install dependencies +RUN uv pip install --system --no-cache -r pyproject.toml + +# Final stage - use minimal Python 3.13 image +FROM python:3.13-slim + +# Set environment variables +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 + +# Create non-root user +RUN useradd -m -u 1001 appuser + +# Copy installed packages from builder +COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin + +# Set working directory +WORKDIR /app + +# Copy application code +COPY --chown=1001:1001 *.py ./ +COPY --chown=1001:1001 frontend/ ./frontend/ +COPY --chown=1001:1001 skills/ ./skills/ + +# Switch to non-root user +USER 1001 + +# Expose port +EXPOSE 8080 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health').read()" + +# Run the application +CMD ["python", "main.py"] + +# Made with Bob diff --git a/ai/langchain-skills-agent/src/agents.py b/ai/langchain-skills-agent/src/agents.py index 7f402024c..bcb52a6e2 100644 --- a/ai/langchain-skills-agent/src/agents.py +++ b/ai/langchain-skills-agent/src/agents.py @@ -4,35 +4,41 @@ Uses the modern approach with tool binding instead of deprecated AgentExecutor. """ +import logging import os from typing import Any, List from dotenv import load_dotenv from langchain_core.messages import HumanMessage, SystemMessage from langchain_core.prompts import ChatPromptTemplate -from langchain_ibm import ChatWatsonx +from langchain_openai import ChatOpenAI load_dotenv() +logger = logging.getLogger(__name__) + def create_llm(): """Create and configure the LLM instance. Returns: - Configured ChatWatsonx instance + Configured ChatOpenAI instance for RedHat AI Inference service """ - - parameters = { - "temperature": 0.7, - "max_tokens": 2048, - } - - return ChatWatsonx( - model_id=os.getenv("INFERENCE_MODEL_NAME", "gpt-3.5-turbo"), - url=os.getenv("INFERENCE_BASE_URL"), - api_key=os.getenv("INFERENCE_API_KEY", ""), - project_id=os.getenv("INFERENCE_PROJECT_ID"), - params=parameters + api_key = os.getenv("IBM_CLOUD_API_KEY") + base_url = os.getenv("INFERENCE_BASE_URL") + model = os.getenv("INFERENCE_MODEL_NAME", "llama-3-3-70b-instruct") + + logger.info("๐ง CONFIGURING LLM") + logger.info(f"Base URL: {base_url}") + logger.info(f"Model: {model}") + logger.info(f"Temperature: 0.7") + logger.info(f"Max Tokens: 2048") + + return ChatOpenAI( + api_key=api_key, + base_url=base_url, + model=model, + temperature=0.7, ) @@ -43,20 +49,35 @@ def get_system_message() -> str: Returns: System message string """ - return """You are a helpful travel and weather assistant with access to specialized skills. + return """You are a helpful travel and weather assistant. Your job is to help users plan trips by providing practical, actionable information. -Your capabilities include: -- Providing weather forecasts for any location -- Recommending travel destinations based on preferences -- Converting currencies for travel planning +IMPORTANT INSTRUCTIONS: +- When you call tools, WAIT for their results before responding to the user +- Use the actual data returned by the tools in your response +- DO NOT explain what tools you're calling or how you work +- DO NOT mention function calls, APIs, or technical details +- Provide direct, helpful answers based on the tool results +- Format your responses as a helpful travel guide would -When users ask questions: -1. Understand their needs clearly -2. Use the appropriate skills to gather information -3. Provide comprehensive, well-formatted responses -4. Be friendly and helpful +Your capabilities: +- Get weather forecasts for any location +- Recommend travel destinations based on preferences and budget +- Convert currencies for travel planning -Always format your responses in a clear, readable way. Use the skills available to you to provide accurate and helpful information.""" +When helping users: +1. Call the appropriate tools to gather information +2. Wait for the tool results +3. Synthesize the information into a helpful, natural response +4. Present the information as if you're a knowledgeable travel advisor +5. Be friendly, practical, and focus on what the user needs to know + +Example good response style: +"Based on the current forecast, Paris will have sunny weather for the next 5 days with temperatures around 22ยฐC. For your $2000 budget (approximately โฌ1,850), I recommend staying in the Marais district where you can find mid-range hotels for about โฌ120/night..." + +Example BAD response (never do this): +"I have called the weather_forecast function and the currency_converter function..." + +Always provide natural, helpful responses using the actual data from the tools.""" def create_langchain_agent(tools: List): @@ -70,6 +91,10 @@ def create_langchain_agent(tools: List): """ llm = create_llm() + logger.info(f"๐ BINDING {len(tools)} TOOLS TO LLM") + for tool in tools: + logger.info(f" - {tool.name}: {tool.description[:80]}..." if len(tool.description) > 80 else f" - {tool.name}: {tool.description}") + # Bind tools to the LLM (modern approach) llm_with_tools = llm.bind_tools(tools) diff --git a/ai/langchain-skills-agent/src/frontend/landing_page.py b/ai/langchain-skills-agent/src/frontend/landing_page.py index 4b8610e52..d6350d9bd 100644 --- a/ai/langchain-skills-agent/src/frontend/landing_page.py +++ b/ai/langchain-skills-agent/src/frontend/landing_page.py @@ -144,6 +144,93 @@ def render_landing_page(name: str) -> str: font-size: 2em; margin-bottom: 10px; }} + + .chat-section {{ + background: #f8f9fa; + padding: 30px; + border-radius: 10px; + margin-top: 30px; + }} + + .chat-section h2 {{ + color: #333; + font-size: 1.5em; + margin-bottom: 20px; + }} + + .chat-input-container {{ + display: flex; + gap: 10px; + margin-bottom: 20px; + }} + + .chat-input {{ + flex: 1; + padding: 12px 15px; + border: 2px solid #ddd; + border-radius: 8px; + font-size: 1em; + font-family: inherit; + transition: border-color 0.3s; + }} + + .chat-input:focus {{ + outline: none; + border-color: #667eea; + }} + + .test-button {{ + background: #667eea; + color: white; + border: none; + padding: 12px 30px; + border-radius: 8px; + font-size: 1em; + font-weight: 600; + cursor: pointer; + transition: background 0.3s; + }} + + .test-button:hover {{ + background: #5568d3; + }} + + .test-button:disabled {{ + background: #ccc; + cursor: not-allowed; + }} + + .response-box {{ + background: white; + border: 2px solid #ddd; + border-radius: 8px; + padding: 20px; + min-height: 150px; + max-height: 400px; + overflow-y: auto; + font-family: 'Courier New', monospace; + font-size: 0.9em; + white-space: pre-wrap; + word-wrap: break-word; + display: none; + }} + + .response-box.visible {{ + display: block; + }} + + .loading {{ + color: #667eea; + font-style: italic; + }} + + .error {{ + color: #dc3545; + }} + + .success {{ + color: #28a745; + }}
@@ -200,11 +287,105 @@ def render_landing_page(name: str) -> str: +