### Install SAP AI SDK Orchestration Client Source: https://sap.github.io/ai-sdk/docs/js/next/getting-started Installs the SAP AI SDK Orchestration client using npm. This is the initial step to integrate AI capabilities into your project. ```bash npm install @sap-ai-sdk/orchestration ``` -------------------------------- ### Install Dependencies for LangChain Agents Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Installs necessary npm packages for building agents with LangChain, including SAP AI SDK, LangGraph, and core LangChain libraries. ```bash npm install @sap-ai-sdk/langchain langchain @langchain/langgraph @langchain/core @langchain/mcp-adapters @modelcontextprotocol/sdk zod ``` -------------------------------- ### Initialize Orchestration Client with GPT-4o Source: https://sap.github.io/ai-sdk/docs/js/next/getting-started Initializes the OrchestrationClient with OpenAI's GPT-4o model and a user prompt template. The template defines the structure of the input to the AI model. ```javascript import { OrchestrationClient } from '@sap-ai-sdk/orchestration'; const orchestrationClient = new OrchestrationClient({ promptTemplating: { model: { name: 'gpt-4o' }, prompt: { template: [ { role: 'user', content: 'Answer the question: {{?question}}' } ] } } }); ``` -------------------------------- ### Initialize MCP Client and Get Tools Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Initializes a MultiServerMCPClient with specified configurations to connect to an MCP server. It then retrieves tools from the server, which are used for fetching weather data. Dependencies include '@langchain/mcp-adapters'. ```typescript // NOTE: ALL code changes in this file MUST be reflected in the documentation portal. import { MultiServerMCPClient } from '@langchain/mcp-adapters'; // Create client and connect to server const client = new MultiServerMCPClient({ throwOnLoadError: true, prefixToolNameWithServerName: false, additionalToolNamePrefix: '', useStandardContentBlocks: true, mcpServers: { weather: { command: 'npx', args: ['tsx', './src/tutorials/mcp/weather-mcp-server.ts'] } } }); /** * Fetches tools from the MCP server. * @returns An array of tools for fetching weather data. */ export const getMcpTools = await client.getTools(); ``` -------------------------------- ### Invoke Assistant with Follow-up Question (JavaScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This code demonstrates how to invoke the assistant with a follow-up question to modify the previously generated itinerary. It uses the `Command` object with a `resume` property containing the user's new request. ```javascript response = await app.invoke( new Command({ resume: 'Can you suggest something more outdoorsy?' }), config ); console.log('Assistant:', response.messages.at(-1)?.content); ``` -------------------------------- ### Define Mock Restaurant Tool with LangChain Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Defines a mock 'get_restaurants' tool using LangChain's `tool` function. It uses predefined data to recommend restaurants based on a city, handling cases where data is not available. This tool is useful for initial development and testing. ```typescript import { tool } from '@langchain/core/tools'; import { z } from 'zod'; const mockRestaurantData: Record = { paris: ['Le Comptoir du Relais', "L'As du Fallafel", 'Breizh Café'], reykjavik: ['Dill Restaurant', 'Fish Market', 'Grillmarkaðurinn'] }; const getRestaurantsTool = tool( async ({ city }) => { const restaurants = mockRestaurantData[city.toLowerCase()]; return restaurants ? `Popular restaurants in ${city}: ${restaurants.join(', ')}` : `No restaurant data available for ${city}.`; }, { name: 'get_restaurants', description: 'Get restaurant recommendations for a city', schema: z.object({ city: z.string().meta({ description: 'The city name' }) }) } ); ``` -------------------------------- ### Initialize AzureOpenAiChatClient with Tools Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Initializes the AzureOpenAiChatClient with a specified model and temperature, then binds available tools to the model for use by the agent. Dependencies include the AzureOpenAiChatClient, ToolNode, and tool definitions. ```javascript import { AzureOpenAiChatClient } from '@langchain/openai'; import { ToolNode } from '@langchain/langgraph/prebuilt'; import { getMcpTools } from '../mcp/mcp-adapter.js'; // Define the tools for the agent to use const tools = [...getMcpTools, getRestaurantsTool]; const toolNode = new ToolNode(tools); // Create a model const model = new AzureOpenAiChatClient({ modelName: 'gpt-4o', temperature: 0.7, maxRetries: 0 }); // create a model with access to the tools const modelWithTools = model.bindTools(tools); ``` -------------------------------- ### Initialize OrchestrationClient with Tools Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Initializes the OrchestrationClient with prompt templating details, including the model name and parameters like temperature. It then binds tools to the client for agent utilization. Dependencies include OrchestrationClient, ToolNode, and tool definitions. ```javascript import { OrchestrationClient } from '@sap-ai-sdk/langchain'; import { ToolNode } from '@langchain/langgraph/prebuilt'; import { getMcpTools } from '../mcp/mcp-adapter.js'; const tools = [...getMcpTools, getRestaurantsTool]; // Create a model const model = new OrchestrationClient({ promptTemplating: { model: { name: 'gpt-4o-mini', params: { temperature: 0.7 } } } }); // create a model with access to the tools const modelWithTools = model.bindTools(tools); const toolNode = new ToolNode(tools); ``` -------------------------------- ### Set up Weather MCP Server with Open-Meteo API Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Configures an MCP (Model Context Protocol) server using '@modelcontextprotocol/sdk' to fetch weather data via the Open-Meteo API. It includes geocoding to find city coordinates and then retrieves hourly weather forecasts for one day. Error handling is implemented for API requests. ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import * as z from 'zod/v4'; const server = new McpServer({ name: 'Open-Meteo Weather MCP Server', version: '1.0.0' }); server.tool( 'get_weather', 'Tool to fetch weather details for a specific city', { city: z .string() .meta({ description: 'The name of the city to get the weather for' }) }, async ({ city }) => { try { const geoResponse = await fetch( `https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=10&language=en&format=json` ); const data = await geoResponse.json(); if (!data.results?.length) { return { content: [ { type: 'text', text: `No results found for city: ${city}` } ] }; } const { latitude, longitude } = data.results[0]; const weatherResponse = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,precipitation,apparent_temperature,relative_humidity_2m&forecast_days=1` ); const weatherData = await weatherResponse.json(); return { content: [{ type: 'text', text: JSON.stringify(weatherData, null, 2) }] }; } catch (error) { return { content: [ { type: 'text', text: `Error fetching weather data: ${(error as Error).message}` } ] }; } } ); const transport = new StdioServerTransport(); server.connect(transport); ``` -------------------------------- ### Invoke Assistant with Initial Message (JavaScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This snippet shows how to initialize and invoke the AI assistant with an initial system prompt and a user message requesting a Paris itinerary. It configures the assistant with a thread ID and includes error handling for the invocation. ```javascript const config = { configurable: { thread_id: 'conv-1' } }; // Initial system prompt and user message const initMessages = [ new SystemMessage( `You are a helpful travel assistant. You will generate a 3-item itinerary based on a provided city. You should use weather forecast and restaurant recommendations when creating the itinerary. After presenting the itinerary, ask the user if they are satisfied with it or if they want to make changes.` ), new HumanMessage( "I'm traveling to Paris. Can you help me prepare an itinerary?" ) ]; // Start the agent with initial messages try { let response = await app.invoke({ messages: initMessages }, config); ``` -------------------------------- ### Invoke Agent Command (TypeScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This snippet shows how to invoke an agent with a 'resume' command, simulating user satisfaction with a proposed itinerary. It then logs the assistant's final response. Error handling is included for robustness. ```typescript response = await app.invoke( new Command({ resume: 'Great! Looks perfect' }), config ); console.log('Assistant:', response.messages.at(-1)?.content); } catch (error) { console.error('Error:', error); } ``` -------------------------------- ### Assistant's Tool Calls for Data Fetching (JSON) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This JSON output represents the AI assistant's internal tool calls made in response to the initial user request. It includes calls to 'get_weather' and 'get_restaurants' for Paris, demonstrating how the assistant gathers necessary data. ```json "tool_calls": [ { "id": "call_bnMuoAGpN6zUnpEm1DwqykvV", "name": "get_weather", "args": { "city": "Paris" }, "type": "tool_call" }, { "id": "call_NnlDugZMjAd4JrSqBa4lFpHE", "name": "get_restaurants", "args": { "city": "Paris" }, "type": "tool_call" } ] ``` -------------------------------- ### Function Calling Source: https://sap.github.io/ai-sdk/docs/js/next/foundation-models/openai/chat-completion Guides on how to enable the model to call specific functions by defining tool definitions. Includes an example of temperature conversion and handling tool calls. ```APIDOC ## Function Calling Define and pass tool definitions to enable the model to call specific functions. Here's an example of temperature conversion using tool calls: ### Tool Definition First, define the tool with `name`, `description` and `parameters` properties: ```javascript const convertTemperatureTool: AzureOpenAiChatCompletionTool = { type: 'function', function: { name: 'convert_temperature_to_fahrenheit', description: 'Converts temperature from Celsius to Fahrenheit', parameters: { type: 'object', properties: { temperature: { type: 'number', description: 'The temperature value in Celsius to convert.' } }, required: ['temperature'] } } }; ``` Set `strict` to `true` to ensure function calls adhere to the function schema. For more information refer to the OpenAI documentation. ### Initial Request with Tool Initialize the client and send the initial request with the tool definition: ```javascript const client = new AzureOpenAiChatClient('gpt-4o'); const messages = [ { role: 'user', content: 'Convert 20 degrees Celsius to Fahrenheit.' } ]; const response = await client.run({ messages, tools: [convertTemperatureTool] }); ``` ### Handling Tool Calls When the model decides to use a tool, it returns the function name and input arguments in the response. Use the model response to execute the function. ```javascript const initialResponse = response.data.choices[0].message; messages.push(initialResponse); let toolMessage: AzureOpenAiChatCompletionRequestToolMessage; if (initialResponse.tool_calls) { const toolCall = initialResponse.tool_calls[0]; const name = toolCall.function.name; const args = JSON.parse(toolCall.function.arguments); // Execute the function with the provided arguments const toolResult = callFunction(name, args); toolMessage = { role: 'tool', content: toolResult, tool_call_id: toolCall.id }; } ``` ### Function Routing The `callFunction` function routes the calls to the actual implementations. ```javascript function callFunction(name: string, args: any): string { switch (name) { case 'convert_temperature_to_fahrenheit': return convertTemperatureToFahrenheit(args.temperature); default: throw new Error(`Function: ${name} not found!`); } } function convertTemperatureToFahrenheit(temperature: number): string { return `The temperature in Fahrenheit is ${(temperature * 9) / 5 + 32}°F.`; } ``` ### Final Response Send the function result back to the model to get its final response: ```javascript const finalResponse = await client.run({ messages: [...messages, toolMessage], tools: [convertTemperatureTool] }); console.log(finalResponse.getContent()); ``` ``` -------------------------------- ### Create Weather MCP Server Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Sets up a Model Context Protocol (MCP) server named 'Open-Meteo Weather MCP Server' that provides a tool for fetching weather details based on a city name. It uses Zod for schema validation and fetches data from Open-Meteo APIs. Dependencies include '@modelcontextprotocol/sdk/server/mcp.js', '@modelcontextprotocol/sdk/server/stdio.js', and 'zod/v4'. ```typescript // NOTE: ALL code changes in this file MUST be reflected in the documentation portal. /* eslint-disable import/no-internal-modules */ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import * as z from 'zod/v4'; const server = new McpServer({ name: 'Open-Meteo Weather MCP Server', version: '1.0.0' }); server.tool( 'get_weather', 'Tool to fetch weather details for a specific city', { city: z .string() .meta({ description: 'The name of the city to get the weather for' }) }, async ({ city }) => { try { const geoResponse = await fetch( `https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=10&language=en&format=json` ); const data = await geoResponse.json(); if (!data.results?.length) { return { content: [ { type: 'text', text: `No results found for city: ${city}` } ] }; } const { latitude, longitude } = data.results[0]; const weatherResponse = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,precipitation,apparent_temperature,relative_humidity_2m&forecast_days=1` ); const weatherData = await weatherResponse.json(); return { content: [{ type: 'text', text: JSON.stringify(weatherData, null, 2) }] }; } catch (error) { return { content: [ { type: 'text', text: `Error fetching weather data: ${(error as Error).message}` } ] }; } } ); const transport = new StdioServerTransport(); server.connect(transport); ``` -------------------------------- ### Configure AI Core Service Key Source: https://sap.github.io/ai-sdk/docs/js/next/getting-started Defines the AI Core service key in a .env file for local application execution. This environment variable is crucial for authenticating with the AI Core service. ```dotenv AICORE_SERVICE_KEY='{ "clientid": "...", ... }' ``` -------------------------------- ### Install @sap-ai-sdk/prompt-registry Source: https://sap.github.io/ai-sdk/docs/js/next/ai-core/prompt-registry Installs the SAP AI SDK prompt registry package using npm. It is recommended to use the tilde (~) version range for compatibility due to the presence of generated code. ```bash npm install @sap-ai-sdk/prompt-registry ``` -------------------------------- ### Build and Compile Workflow Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Constructs the LangGraph StateGraph by adding nodes for agent, tools, and human interaction, and defining conditional and direct edges for workflow transitions. It then compiles the graph with a checkpointer for state persistence. Dependencies include StateGraph, MemorySaver, and the defined nodes and edges. ```javascript const workflow = new StateGraph(MessagesAnnotation) .addNode('agent', callModel) .addNode('tools', toolNode) .addNode('askHuman', askHuman) .addConditionalEdges('agent', shouldContinueAgent, ['tools', 'askHuman', END]) .addEdge('tools', 'agent') .addEdge('askHuman', 'agent') .addEdge(START, 'agent'); const memory = new MemorySaver(); const app = workflow.compile({ checkpointer: memory }); ``` -------------------------------- ### Install @sap-ai-sdk/orchestration Source: https://sap.github.io/ai-sdk/docs/js/next/orchestration/chat-completion Installs the necessary package for the SAP AI Core orchestration service using npm. ```bash $ npm install @sap-ai-sdk/orchestration ``` -------------------------------- ### Send Chat Completion Request Source: https://sap.github.io/ai-sdk/docs/js/next/getting-started Sends a chat completion request to the initialized OrchestrationClient, providing a value for the 'question' placeholder. The response content, which is the generated text, is then logged to the console. ```javascript const response = await orchestrationClient.chatCompletion({ placeholderValues: { question: 'Why is the phrase "Hello world!" so famous?' } }); console.log(response.getContent()); ``` -------------------------------- ### Log Assistant Response and Next State (JavaScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This JavaScript code snippet demonstrates how to log the assistant's final response content and the next expected state after an interaction. It uses `console.log` to display the assistant's message and the value of the 'next' state. ```javascript console.log('Assistant:', response.messages.at(-1)?.content); console.log('next: ', (await app.getState(config)).next); ``` -------------------------------- ### Log Next State Value (JavaScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This snippet shows how to retrieve and log the 'next' state of the assistant's conversation flow. It's used to determine the subsequent actions or expected inputs after a particular turn. ```javascript next: [ 'askHuman' ] ``` -------------------------------- ### Integrate MCP Server with LangChain using MCP Adapter Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Sets up LangChain's MCP Adapter to connect to the MCP server, specifically the weather service. This allows LangChain agents to discover and utilize tools exposed by the MCP server, such as fetching weather data. ```typescript import { MultiServerMCPClient } from '@langchain/mcp-adapters'; // Create client and connect to server const client = new MultiServerMCPClient({ throwOnLoadError: true, prefixToolNameWithServerName: false, additionalToolNamePrefix: '', useStandardContentBlocks: true, mcpServers: { weather: { command: 'npx', args: ['tsx', './src/tutorials/mcp/weather-mcp-server.ts'] } } }); /** * Fetches tools from the MCP server. * @returns An array of tools for fetching weather data. */ export const getMcpTools = await client.getTools(); ``` -------------------------------- ### Install SAP AI SDK Foundation Models Source: https://sap.github.io/ai-sdk/docs/js/next/foundation-models Installs the @sap-ai-sdk/foundation-models package using npm. This is the primary step to integrate foundation models into your SAP AI projects. ```bash npm install @sap-ai-sdk/foundation-models ``` -------------------------------- ### Install @sap-ai-sdk/ai-api Source: https://sap.github.io/ai-sdk/docs/js/next/ai-core/ai-api Installs the @sap-ai-sdk/ai-api package using npm. This package contains generated code and requires careful version management. ```bash $ npm install @sap-ai-sdk/ai-api ``` -------------------------------- ### Install @sap-ai-sdk/document-grounding Source: https://sap.github.io/ai-sdk/docs/js/next/ai-core/document-grounding Installs the document grounding package using npm. It's recommended to use the tilde version range for compatibility. ```bash $ npm install @sap-ai-sdk/document-grounding ``` -------------------------------- ### Install @sap-ai-sdk/langchain using npm Source: https://sap.github.io/ai-sdk/docs/js/next/langchain Installs the @sap-ai-sdk/langchain package using npm. It's important to ensure the installed @langchain/core version matches the one used by the SAP SDK package. ```bash npm install @sap-ai-sdk/langchain ``` -------------------------------- ### Travel Itinerary Agent Main Logic (TypeScript) Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents This TypeScript code defines the main logic for a travel itinerary planner agent. It sets up a StateGraph from LangGraph, integrates with Azure OpenAI for LLM capabilities, and uses MCP tools for fetching weather and restaurant data. It handles conversation flow, tool usage, and user interaction. ```TypeScript // NOTE: ALL code changes in this file MUST be reflected in the documentation portal. /* eslint-disable no-console, import/no-internal-modules*/ import { StateGraph, MessagesAnnotation, MemorySaver, START, END, interrupt, Command } from '@langchain/langgraph'; import { ToolNode } from '@langchain/langgraph/prebuilt'; import { AzureOpenAiChatClient } from '@sap-ai-sdk/langchain'; import { HumanMessage, SystemMessage } from '@langchain/core/messages'; import { tool } from '@langchain/core/tools'; import * as z from 'zod/v4'; import { getMcpTools } from './mcp/mcp-adapter.js'; import type { AIMessage } from '@langchain/core/messages'; /** * This example demonstrates how to create a travel itinerary assistant using LangGraph and MCP. * The assistant can check the weather and recommend restaurants based on the city provided. * It uses tools (defined and fetched from MCP server) to fetch weather and restaurant data, and maintains conversation context. */ const mockRestaurantData: Record = { paris: ['Le Comptoir du Relais', "L'As du Fallafel", 'Breizh Café'], reykjavik: ['Dill Restaurant', 'Fish Market', 'Grillmarkaðurinn'] }; const getRestaurantsTool = tool( async ({ city }) => { const restaurants = mockRestaurantData[city.toLowerCase()]; return restaurants ? `Popular restaurants in ${city}: ${restaurants.join(', ')}` : `No restaurant data available for ${city}.`; }, { name: 'get_restaurants', description: 'Get restaurant recommendations for a city', schema: z.object({ city: z.string().meta({ description: 'The city name' }) }) } ); // Define the tools for the agent to use const tools = [...getMcpTools, getRestaurantsTool]; const toolNode = new ToolNode(tools); // Create a model const model = new AzureOpenAiChatClient({ modelName: 'gpt-4o', temperature: 0.7, maxRetries: 0 }); // create a model with access to the tools const modelWithTools = model.bindTools(tools); async function shouldContinueAgent({ messages }: typeof MessagesAnnotation.State) { const lastMessage = messages.at(-1) as AIMessage; // If there are tool calls, go to tools if (lastMessage.tool_calls?.length) { return 'tools'; } // Check if agent's message is a farewell (indicating user was satisfied) const result = await model.invoke([ new SystemMessage( 'You are a classifier. Respond with exactly "FAREWELL" if this is a farewell/goodbye message wishing someone happy travels. Respond with exactly "CONTINUE" if the conversation should continue.' ), new HumanMessage(`Assistant message: "${lastMessage.content}"`) ]); return result.content === 'FAREWELL' ? END : 'askHuman'; } async function askHuman() { // This is where the actual interrupt happens const humanResponse: string = interrupt( 'Do you want to adjust the itinerary?' ); return { messages: [new HumanMessage(humanResponse)] }; } async function callModel({ messages }: typeof MessagesAnnotation.State) { const response = await modelWithTools.invoke(messages); return { messages: [response] }; } const workflow = new StateGraph(MessagesAnnotation) .addNode('agent', callModel) .addNode('tools', toolNode) .addNode('askHuman', askHuman) .addConditionalEdges('agent', shouldContinueAgent, ['tools', 'askHuman', END]) .addEdge('tools', 'agent') .addEdge('askHuman', 'agent') .addEdge(START, 'agent'); const memory = new MemorySaver(); const app = workflow.compile({ checkpointer: memory }); const config = { configurable: { thread_id: 'conv-1' } }; // Initial system prompt and user message const initMessages = [ new SystemMessage( `You are a helpful travel assistant. You will generate a 3-item itinerary based on a provided city. You should use weather forecast and restaurant recommendations when creating the itinerary. After presenting the itinerary, ask the user if they are satisfied with it or if they want to make changes.` ), new HumanMessage( "I'm traveling to Paris. Can you help me prepare an itinerary?" ) ]; // Start the agent with initial messages try { let response = await app.invoke({ messages: initMessages }, config); console.log('Assistant:', response.messages.at(-1)?.content); console.log('next: ', (await app.getState(config)).next); response = await app.invoke( new Command({ resume: 'Can you suggest something more outdoorsy?' }), config ); console.log('Assistant:', response.messages.at(-1)?.content); response = await app.invoke( } ``` -------------------------------- ### Define Agent Routing Logic Source: https://sap.github.io/ai-sdk/docs/js/next/tutorials/getting-started-with-agents Defines the logic for continuing the agent's turn based on the last message. It checks for tool calls or uses a classifier model to determine if the conversation should continue or end. Dependencies include AIMessage, SystemMessage, HumanMessage, and the model instance. ```javascript async function shouldContinueAgent({ messages }: typeof MessagesAnnotation.State) { const lastMessage = messages.at(-1) as AIMessage; // If there are tool calls, go to tools if (lastMessage.tool_calls?.length) { return 'tools'; } // Check if agent's message is a farewell (indicating user was satisfied) const result = await model.invoke([ new SystemMessage( 'You are a classifier. Respond with exactly "FAREWELL" if this is a farewell/goodbye message wishing someone happy travels. Respond with exactly "CONTINUE" if the conversation should continue.' ), new HumanMessage(`Assistant message: "${lastMessage.content}") ]); return result.content === 'FAREWELL' ? END : 'askHuman'; } async function askHuman() { // This is where the actual interrupt happens const humanResponse: string = interrupt( 'Do you want to adjust the itinerary?' ); return { messages: [new HumanMessage(humanResponse)] }; } async function callModel({ messages }: typeof MessagesAnnotation.State) { const response = await modelWithTools.invoke(messages); return { messages: [response] }; } ``` -------------------------------- ### Chat Completion Source: https://sap.github.io/ai-sdk/docs/js/next/langchain/openai Shows how to interact with Azure OpenAI chat models on SAP AI Core using the `AzureOpenAiChatClient`. Includes a basic prompt example and an advanced example with templating and output parsing. ```APIDOC ## Chat Completion The `AzureOpenAiChatClient` allows interaction with Azure OpenAI chat models on SAP AI Core. Pass a prompt to invoke the client. ```javascript const response = await chatClient.invoke("What's the capital of France?"); ``` Below is an advanced example demonstrating the usage of templating and output parsing. ```javascript import { AzureOpenAiChatClient } from '@sap-ai-sdk/langchain'; import { StringOutputParser } from '@langchain/core/output_parsers'; import { ChatPromptTemplate } from '@langchain/core/prompts'; // Initialize the client const chatClient = new AzureOpenAiChatClient({ modelName: 'gpt-4o' }); // Create a prompt template const promptTemplate = ChatPromptTemplate.fromMessages([ ['system', 'Answer the following in {language}:'], ['user', '{text}'] ]); // Create an output parser const parser = new StringOutputParser(); // Chain together template, client and parser const llmChain = promptTemplate.pipe(chatClient).pipe(parser); // Invoke the chain return llmChain.invoke({ language: 'german', text: 'What is the capital of France?' }); ``` ``` -------------------------------- ### Advanced Chat Completion with Templating and Output Parsing Source: https://sap.github.io/ai-sdk/docs/js/next/langchain/openai An advanced example of using `AzureOpenAiChatClient` with LangChain's templating and output parsing. It chains a `ChatPromptTemplate`, the `AzureOpenAiChatClient`, and a `StringOutputParser` to format and retrieve a response in a specified language. ```typescript import { AzureOpenAiChatClient } from '@sap-ai-sdk/langchain'; import { StringOutputParser } from '@langchain/core/output_parsers'; import { ChatPromptTemplate } from '@langchain/core/prompts'; // Initialize the client const chatClient = new AzureOpenAiChatClient({ modelName: 'gpt-4o' }); // Create a prompt template const promptTemplate = ChatPromptTemplate.fromMessages([ ['system', 'Answer the following in {language}:'], ['user', '{text}'] ]); // Create an output parser const parser = new StringOutputParser(); // Chain together template, client and parser const llmChain = promptTemplate.pipe(chatClient).pipe(parser); // Invoke the chain return llmChain.invoke({ language: 'german', text: 'What is the capital of France?' }); ``` -------------------------------- ### Load Environment Variables with dotenv Source: https://sap.github.io/ai-sdk/docs/js/next/connecting-to-ai-core This example shows how to load environment variables, such as `AICORE_SERVICE_KEY`, from a `.env` file using the `dotenv` library in a Node.js environment. Alternatively, Node.js can load environment files directly using a command-line flag. ```javascript require('dotenv').config(); // Loads .env file\n// Or run node --env-file=.env your_app.js ``` -------------------------------- ### Provide AI Core Service Key via Environment Variable Source: https://sap.github.io/ai-sdk/docs/js/next/connecting-to-ai-core This example demonstrates how to set the `AICORE_SERVICE_KEY` environment variable with the JSON credentials of an AI Core service key. The SAP Cloud SDK for AI reads this variable for local development. ```bash AICORE_SERVICE_KEY='{\n "clientid": "...",\n ...\n}' ``` -------------------------------- ### Chat Completion with Azure OpenAI Client Source: https://sap.github.io/ai-sdk/docs/js/next/langchain/openai Shows a basic example of invoking the `AzureOpenAiChatClient` to get a response from an Azure OpenAI chat model. A simple prompt is passed directly to the `invoke` method. ```typescript const response = await chatClient.invoke("What's the capital of France?"); ``` -------------------------------- ### List Prompt Templates (SAP AI Core) Source: https://sap.github.io/ai-sdk/docs/js/next/ai-core/prompt-registry Demonstrates how to list prompt templates from the SAP AI Core prompt registry service using the PromptTemplatesApi. Requires the SDK and a defined scenario. ```typescript const response: PromptTemplateListResponse = await PromptTemplatesApi.listPromptTemplates({ scenario: 'test' }).execute(); ``` -------------------------------- ### Client Initialization Source: https://sap.github.io/ai-sdk/docs/js/next/foundation-models Demonstrates how to initialize clients for generative AI foundation models like Azure OpenAI Chat and Embedding. Covers specifying model names, versions, resource groups, and deployment IDs. ```APIDOC ## Client Initialization Initialize a client with the model name. If model version is not specified, it is set to `latest`. The current available clients are: - `AzureOpenAiChatClient` - `AzureOpenAiEmbeddingClient` Take the `AzureOpenAiChatClient` as an example, use the following code to initialize a client: ``` import { AzureOpenAiChatClient } from '@sap-ai-sdk/foundation-models'; const client = new AzureOpenAiChatClient('gpt-4o'); ``` The deployment ID will be implicitly fetched from the `default` resource group. By default, the deployment information is cached for five minutes, including deployment ID, model name, and model version. When using other resource groups, you can specify the `resourceGroup` parameter. ``` const client = new AzureOpenAiChatClient({ modelName: 'gpt-4o', // modelVersion: '2024-08-06', // optional resourceGroup: 'my-resource-group' }); ``` Alternatively, you can also provide a deployment ID instead of model name (and model version). ``` const client = new AzureOpenAiChatClient({ // resourceGroup: 'my-resource-group', // optional deploymentId: 'd1234' }); ``` **Tip:** When initializing a client for using a foundation model, it is equivalent to provide - a combination of model name and model version - or deployment ID to identify a model within a Resource Group. If multiple deployments were created with the same model name and version, the first deployment will be used. ``` -------------------------------- ### Initialize OrchestrationClient with Basic Configuration (JavaScript) Source: https://sap.github.io/ai-sdk/docs/js/next/langchain/orchestration Demonstrates initializing the OrchestrationClient from '@sap-ai-sdk/langchain' with basic configuration for prompt templating and specifying the model name. ```javascript import { OrchestrationClient } from '@sap-ai-sdk/langchain'; const config: OrchestrationModuleConfig = { promptTemplating: { model: { name: 'gpt-4o' } } }; const client = new OrchestrationClient(config); ``` -------------------------------- ### OrchestrationClient Initialization Source: https://sap.github.io/ai-sdk/docs/js/next/langchain/orchestration Initializes the OrchestrationClient with basic configuration for prompt templating and model selection. ```APIDOC ## OrchestrationClient Initialization Initializes the `OrchestrationClient` for LangChain integration. ### Method `constructor` ### Endpoint N/A (Client-side initialization) ### Parameters #### Request Body - **config** (OrchestrationModuleConfig) - Required - Configuration for the orchestration client, including prompt templating and model details. - **promptTemplating** (object) - Required - Configuration for prompt templating. - **model** (object) - Required - Model configuration. - **name** (string) - Required - The name of the model to use (e.g., 'gpt-4o'). ### Request Example ```javascript import { OrchestrationClient } from '@sap-ai-sdk/langchain'; const config = { promptTemplating: { model: { name: 'gpt-4o' } } }; const client = new OrchestrationClient(config); ``` ### Response No direct response, creates an instance of `OrchestrationClient`. #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Configure Static Prompt Template with Placeholders Source: https://sap.github.io/ai-sdk/docs/js/next/orchestration/chat-completion Sets up a static prompt template using the `promptTemplating.prompt.template` configuration. Placeholders within the template are replaced by values provided in `placeholderValues` during a `chatCompletion()` call. This is ideal for prompts with a consistent base structure. ```javascript const orchestrationClient = new OrchestrationClient({ promptTemplating: { model: { name: 'gpt-4o' }, prompt: { template: [ { role: 'user', content: 'What is the capital of {{?country}}?' } ] } } }); const response = await orchestrationClient.chatCompletion({ placeholderValues: { country: 'France' } }); ``` -------------------------------- ### Define JSON Schema Response Format (TypeScript) Source: https://sap.github.io/ai-sdk/docs/js/next/orchestration/chat-completion Configures the `response_format` parameter to enforce a JSON schema for model outputs when not calling tools. This example defines a schema for country and capital names. ```typescript const templating: TemplatingModuleConfig = { response_format: { type: 'json_schema', json_schema: { name: 'capital_response', strict: true, schema: { type: 'object', properties: { country_name: { type: 'string', description: 'The name of the country provided by the user.' }, capital: { type: 'string', description: 'The capital city of the country.' } }, required: ['country_name', 'capital'] } } } }; ``` -------------------------------- ### Configure Document Grounding with Orchestration Client Source: https://sap.github.io/ai-sdk/docs/js/next/orchestration/chat-completion Demonstrates setting up the OrchestrationClient for document grounding, defining placeholders, filters, and data repositories for external context integration. ```javascript const orchestrationClient = new OrchestrationClient({ promptTemplating: { model: { name: 'gpt-4o' } }, grounding: buildDocumentGroundingConfig({ placeholders: { input: ['groundingRequest'], output: 'groundingOutput' }, // metadata_params: ['PARAM_NAME'] filters: [ { id: 'FILTER_ID', // data_repository_type: 'vector', // optional, default to 'vector' data_repositories: ['REPOSITORY_ID'] } ] }) }); const response = await orchestrationClient.chatCompletion({ messages: [ { role: 'user', content: 'UserQuestion: {{?groundingRequest}} Context: {{?groundingOutput}}' } ], placeholderValues: { groundingRequest: 'Give me a short introduction of SAP AI Core.' } }); ``` -------------------------------- ### Response Formatting with JSON Schema Source: https://sap.github.io/ai-sdk/docs/js/next/foundation-models/openai/chat-completion Demonstrates how to specify a JSON schema for model responses to ensure structured output. Includes an example using strict JSON schema validation and integration with Zod for schema definition. ```APIDOC ## Response Format For general response formatting, use the `response_format` parameter. It is useful when the model is not calling a tool and should still return a structured response. ### Example: Strict JSON Schema Response This example returns a JSON Schema with `strict: true` to let the response adhere to the schema definition. ```javascript const response = await client.run({ messages: [ { role: 'user', content: 'What is the capital of France?' } ], response_format: { type: 'json_schema', json_schema: { description: 'Response format for the capital of France.', name: 'capital_of_france', schema: { type: 'object', properties: { capital: { type: 'string', description: 'The capital city of France.' }, population: { type: 'number', description: 'The population of the capital city.' } }, additionalProperties: false, // Ensures no additional properties are allowed required: ['capital', 'population'] }, strict: true } } }); console.log(response.getContent()); ``` ### Example: Zod Schema Integration You can also define JSON schema using Zod schema as shown below: ```javascript import * as z from 'zod'; import { toJsonSchema } from '@langchain/core/utils/json_schema'; import { AzureOpenAiResponseFormatJsonSchema } from '@sap-ai-sdk/foundation-models'; const countryCapitalSchema = z .object({ population: z.number(), capital: z.string() }) .strict(); const response_format: AzureOpenAiResponseFormatJsonSchema = { type: 'json_schema', json_schema: { name: 'capital_response', strict: true, schema: toJsonSchema(countryCapitalSchema) } }; ``` ``` -------------------------------- ### Load Local Prompt Template from YAML Source: https://sap.github.io/ai-sdk/docs/js/next/orchestration/chat-completion Demonstrates loading a prompt template from a local YAML file by reading its content and passing it as a string to the `promptTemplating.prompt` property. This method is beneficial for local testing of prompt templates before they are integrated into the Prompt Registry. The YAML content is parsed and validated. ```javascript import { readFileSync } from 'fs'; import { OrchestrationClient } from '@sap-ai-sdk/orchestration'; // Read the YAML file containing the prompt template const yamlTemplate = readFileSync('./path/to/prompt-template.yaml', 'utf-8'); const orchestrationClient = new OrchestrationClient({ promptTemplating: { model: { name: 'gpt-4o' }, prompt: yamlTemplate } }); const response = await orchestrationClient.chatCompletion({ placeholderValues: { country: 'France' } }); ``` -------------------------------- ### Create a Configuration with AI API Source: https://sap.github.io/ai-sdk/docs/js/next/ai-core/ai-api Shows how to create a configuration for an AI model using ConfigurationApi.configurationCreate. This involves specifying the configuration name, executable ID, scenario ID, and parameter/artifact bindings. ```typescript async function createConfiguration() { const requestBody: ConfigurationBaseData = { name: 'gpt-4o', executableId: 'azure-openai', scenarioId: 'foundation-models', parameterBindings: [ { key: 'modelName', value: 'gpt-4o' }, { key: 'modelVersion', value: 'latest' } ], inputArtifactBindings: [] }; const responseData: ConfigurationCreationResponse = await ConfigurationApi.configurationCreate(requestBody, { 'AI-Resource-Group': 'default' }).execute(); return responseData; } ``` -------------------------------- ### Implement Function Routing for AI Tool Calls (TypeScript) Source: https://sap.github.io/ai-sdk/docs/js/next/foundation-models/openai/chat-completion Provides the implementation for routing AI tool calls to their respective functions. The `callFunction` handles different function names and passes the correct arguments to the implementation. This example includes a specific handler for `convert_temperature_to_fahrenheit`. ```typescript function callFunction(name: string, args: any): string { switch (name) { case 'convert_temperature_to_fahrenheit': return convertTemperatureToFahrenheit(args.temperature); default: throw new Error(`Function: ${name} not found!`); } } function convertTemperatureToFahrenheit(temperature: number): string { return `The temperature in Fahrenheit is ${(temperature * 9) / 5 + 32}°F.`; } ```