diff --git a/11-integrating-with-function-calling/js-githubmodels/app.js b/11-integrating-with-function-calling/js-githubmodels/app.js new file mode 100644 index 000000000..64e4cb011 --- /dev/null +++ b/11-integrating-with-function-calling/js-githubmodels/app.js @@ -0,0 +1,167 @@ +import ModelClient from "@azure-rest/ai-inference"; +import { AzureKeyCredential } from "@azure/core-auth"; + +const token = process.env["GITHUB_TOKEN"]; +const endpoint = "https://models.inference.ai.azure.com"; + +/* By using the Azure AI Inference SDK, you can easily experiment with different models + by modifying the value of `modelName` in the code below. For this code sample + you need a model supporting tools. The following compatible models are + available in the GitHub Models service: + + Cohere: Cohere-command-r, Cohere-command-r-plus + Mistral AI: Mistral-large, Mistral-large-2407, Mistral-Nemo, Mistral-small + Azure OpenAI: gpt-4o-mini, gpt-4o */ +const modelName = "gpt-4o"; + +function getFlightInfo({ originCity, destinationCity }) { + if (originCity === "Seattle" && destinationCity === "Miami") { + return JSON.stringify({ + airline: "Delta", + flight_number: "DL123", + flight_date: "May 7th, 2024", + flight_time: "10:00AM" + }); + } + return JSON.stringify({ error: "No flights found between the cities" }); +} + +function getHotelInfo({ destination }) { + if ( destination === "Miami") { + return JSON.stringify({ + hotelName: "Contoso Suites" + }); + } + return JSON.stringify({ error: "No available hotels found in this city" }); +} + +const namesToFunctions = { + getFlightInfo: (data) => + getFlightInfo(data), + getHotelInfo: (data) => + getHotelInfo(data) +}; + +export async function main() { + + const tool = { + "type": "function", + "function": { + name: "getFlightInfo", + description: "Returns information about the next flight between two cities." + + "This includes the name of the airline, flight number and the date and time" + + "of the next flight", + parameters: { + "type": "object", + "properties": { + "originCity": { + "type": "string", + "description": "The name of the city where the flight originates", + }, + "destinationCity": { + "type": "string", + "description": "The flight destination city", + }, + }, + "required": [ + "originCity", + "destinationCity" + ], + }, + + } + }; + + const hotels ={ + "type": "function", + "function": { + name: "getHotelInfo", + description: "Returns information about the hotel of the destination city.", + parameters: { + "type": "object", + "properties": { + "destination": { + "type": "string", + "description": "The city that the traveller would like to stay", + }, + }, + "required": [ + "destination" + ], + }, + } + + } + + const client = new ModelClient(endpoint, new AzureKeyCredential(token)); + + let messages = [ + { role: "system", content: "You an assistant that helps users find flight and hotel information." }, + { role: "user", content: "I'm interested in going to Miami and staying in a hotel." }, + // { role: "user", content: "I'm interested in going to Seattle. Are there flights to Denver?" }, + + + + + ]; + + let response = await client.path("/chat/completions").post({ + body: { + messages: messages, + tools: [tool, hotels], + model: modelName + } + }); + if (response.status !== "200") { + throw response.body.error; + } + + // We expect the model to ask for a tool call + if (response.body.choices[0].finish_reason === "tool_calls") { + + // Append the model response to the chat history + messages.push(response.body.choices[0].message); + + // We expect a single tool call + if (response.body.choices[0].message && response.body.choices[0].message.tool_calls.length === 1) { + + const toolCall = response.body.choices[0].message.tool_calls[0]; + // We expect the tool to be a function call + if (toolCall.type === "function") { + const toolCall = response.body.choices[0].message.tool_calls[0]; + // Parse the function call arguments and call the function + const functionArgs = JSON.parse(toolCall.function.arguments); + console.log(`Calling function \`${toolCall.function.name}\` with arguments ${toolCall.function.arguments}`); + const callableFunc = namesToFunctions[toolCall.function.name]; + const functionReturn = callableFunc(functionArgs); + console.log(`Function returned = ${functionReturn}`); + + // Append the function call result fo the chat history + messages.push( + { + "tool_call_id": toolCall.id, + "role": "tool", + "name": toolCall.function.name, + "content": functionReturn, + } + ) + + response = await client.path("/chat/completions").post({ + body: { + messages: messages, + tools: [tool, hotels], + model: modelName + } + }); + if (response.status !== "200") { + throw response.body.error; + } + console.log(`Model response = ${response.body.choices[0].message.content}`); + } + } + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); \ No newline at end of file diff --git a/11-integrating-with-function-calling/js-githubmodels/package-lock.json b/11-integrating-with-function-calling/js-githubmodels/package-lock.json new file mode 100644 index 000000000..ccc05d191 --- /dev/null +++ b/11-integrating-with-function-calling/js-githubmodels/package-lock.json @@ -0,0 +1,285 @@ +{ + "name": "js-githubmodels", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@azure-rest/ai-inference": "latest", + "@azure/core-auth": "latest", + "@azure/core-sse": "latest" + } + }, + "node_modules/@azure-rest/ai-inference": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@azure-rest/ai-inference/-/ai-inference-1.0.0-beta.2.tgz", + "integrity": "sha512-xPnXJmldQ7vufTT1GtoHPk+korWFnl72whoDB34tb9DALTGGBKIAWobDQBMGYdV2ce0/KdhRFPwnfeZjNyfVsw==", + "license": "MIT", + "dependencies": { + "@azure-rest/core-client": "^2.1.0", + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.7.2", + "@azure/core-lro": "^2.6.0", + "@azure/core-rest-pipeline": "^1.14.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure-rest/core-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.2.0.tgz", + "integrity": "sha512-2uPSZPRb2TRyYONl5IcsWhX7C1xbm6Gof/tcLlDnYg7fCVcEfASfySKZ9OTHxhNeFgo79LhrT6juEoxTHvrXkQ==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-rest-pipeline": "^1.5.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure-rest/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", + "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.8.0.tgz", + "integrity": "sha512-YvFMowkXzLbXNM11yZtVLhUCmuG0ex7JKOH366ipjmHBhL3vpDcPAeWF+jf0X+jVXwFqo3UhsWUq4kH0ZPdu/g==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-lro": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", + "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-lro/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz", + "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.9.0", + "@azure/logger": "^1.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-sse": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@azure/core-sse/-/core-sse-2.1.3.tgz", + "integrity": "sha512-KSSdIKy8kvWCpYr8Hzpu22j3wcXsVTYE0IlgmI1T/aHvBDsLgV91y90UTfVWnuiuApRLCCVC4gS09ApBGOmYQA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", + "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.10.0.tgz", + "integrity": "sha512-dqLWQsh9Nro1YQU+405POVtXnwrIVqPyfUzc4zXCbThTg7+vNNaiMkwbX9AMXKyoFYFClxmB3s25ZFr3+jZkww==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz", + "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + } + } +} diff --git a/11-integrating-with-function-calling/js-githubmodels/package.json b/11-integrating-with-function-calling/js-githubmodels/package.json new file mode 100644 index 000000000..2074585e8 --- /dev/null +++ b/11-integrating-with-function-calling/js-githubmodels/package.json @@ -0,0 +1,8 @@ +{ + "type": "module", + "dependencies": { + "@azure-rest/ai-inference": "latest", + "@azure/core-auth": "latest", + "@azure/core-sse": "latest" + } +} \ No newline at end of file