Skip to content

Commit

Permalink
start adding v3 api that adds a basic function
Browse files Browse the repository at this point in the history
  • Loading branch information
crpietschmann committed May 7, 2024
1 parent 2725e17 commit 3ba94c5
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 2 deletions.
27 changes: 27 additions & 0 deletions app/nodejs/simple/api/functions/downloadHtmlToMarkdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const axios = require('axios');
const cheerio = require('cheerio');
const turndown = require('turndown');

async function downloadHtmlToMarkdown(url) {
try {
// Fetch HTML content from the URL
const response = await axios.get(url);
const html = response.data;

// Load HTML into Cheerio
const $ = cheerio.load(html);

// Initialize Turndown converter
const turndownService = new turndown();

// Convert HTML to Markdown
const markdown = turndownService.turndown($.html());

return markdown;
} catch (error) {
console.error('downloadHtmlToMarkdown Error:', error);
throw error;
}
}

module.exports = downloadHtmlToMarkdown;
236 changes: 236 additions & 0 deletions app/nodejs/simple/api/v3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
const { OpenAIClient, AzureKeyCredential } = require("@azure/openai");

const azure_openai_endpoint = process.env["AZURE_OPENAI_API_ENDPOINT"];
const azure_openai_api_key = process.env["AZURE_OPENAI_API_KEY"];
const azure_openai_deployment = process.env["AZURE_OPENAI_API_DEPLOYMENT_NAME"];

const azure_search_endpoint = process.env["AZURE_SEARCH_ENDPOINT"];
const azure_search_key = process.env["AZURE_SEARCH_KEY"];
const azure_search_index_name = process.env["AZURE_SEARCH_INDEX_NAME"];


// Import Functions Used
const downloadHtmlToMarkdown = require('./functions/downloadHtmlToMarkdown');


// Store conversation history in memory for demonstration purposes.
// In a production environment, consider storing this data in a persistent store.
let conversationHistory = [];
let rawConversationHistory = [];

function clearConversationHistory() {
conversationHistory = [
{ role: "system", content: "" }
];
rawConversationHistory = [];
}
clearConversationHistory();

function appendConversationHistory(role, content, raw) {
conversationHistory.push({ role: role, content: content });
rawConversationHistory.push({ role: role, content: content, raw: raw });
}

module.exports = (app) => {
/**
* @openapi
* /v3/chat:
* post:
* tags:
* - v3
* description: Perform Chat Completion
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* prompt:
* type: string
* default: ""
* responses:
* 200:
* description: Returns the OpenAI chat completion response.
* responseBody:
* content:
* application/json:
* schema:
* type: object
*/
app.post(`/v3/chat`, async (req, res) => {
const prompt = req.body.prompt;
if (!prompt) {
return res.status(400).send('Prompt is required');
}

console.info(`\n\nUser Prompt:\n${prompt}`);

// Add the user's prompt to the conversation history
appendConversationHistory("user", prompt);

try {
// https://learn.microsoft.com/javascript/api/%40azure/openai/openaiclient?view=azure-node-preview
const chatClient = new OpenAIClient(
azure_openai_endpoint,
new AzureKeyCredential(azure_openai_api_key)
);

// const chatClient = new OpenAIClient(
// azure_openai_endpoint,
// new AzureKeyCredential(azure_openai_api_key),
// {
// apiVersion: "2024-03-01-preview"
// });

// https://learn.microsoft.com/javascript/api/%40azure/openai/openaiclient
const chatResponse = await chatClient.getChatCompletions(
azure_openai_deployment, // deployment name
conversationHistory, // chat request messages array
{ // getCompletionsOptions - https://learn.microsoft.com/javascript/api/%40azure/openai/getchatcompletionsoptions

// https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions
// https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling?tabs=python
// ERROR: 'Functions are not supported for this API version or this model version. To learn how to user use function calling with Azure OpenAI Service. Please refer to this wiki https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling?tabs=python'
tools: [
{
type: "function",
function: {
name: "downloadHtmlToMarkdown",
description: "Get the contents of a web page URL",
parameters: {
type: "object",
properties: {
url: {
type: "string",
description: "The web page URL of the page to read, e.g. https://build5nines.com/category/page"
}
}
},
required: ["url"]
}
}
],
tool_choice: "auto", // this is the default behavior when tools are specified anyway

/*
functions: [
// https://learn.microsoft.com/en-us/javascript/api/%40azure/openai/functiondefinition?view=azure-node-preview
{
name: "downloadHtmlToMarkdown",
description: "Get the contents of a web page URL",
parameters: {
"url": {
type: "string",
description: "The web page URL of the page to read, e.g. https://build5nines.com/category/page"
}
}
*
parameters: [
{
type: "object",
properties: {
url: {
type: "string",
description: "The web page URL of the page to read, e.g. https://build5nines.com/category/page"
}
}
}
]
*
}
],
*/

azureExtensionOptions: { //https://learn.microsoft.com/javascript/api/%40azure/openai/getchatcompletionsoptions?view=azure-node-preview#@azure-openai-getchatcompletionsoptions-azureextensionoptions
// https://learn.microsoft.com/en-us/javascript/api/%40azure/openai/azurechatextensionconfiguration?view=azure-node-preview
extensions: [
// https://learn.microsoft.com/en-us/javascript/api/%40azure/openai/azureextensionsoptions?view=azure-node-preview#@azure-openai-azureextensionsoptions-extensions
// https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/azure-search.md
{
type: 'AzureCognitiveSearch',
endpoint: azure_search_endpoint,
indexName: azure_search_index_name,
key: azure_search_key,

// Whether queries should be restricted to use of indexed data. Default is True.
in_scope: false,

// The query type to use with Azure Search. Default is simple
queryType: 'simple', // https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/azure-search.md#query-type

// The configured strictness of the search relevance filtering. The higher of strictness, the higher of the precision but lower recall of the answer. Default is 3.
strictness: 2, // https://learn.microsoft.com/javascript/api/@azure/openai/azurecognitivesearchchatextensionconfiguration?view=azure-node-preview#@azure-openai-azurecognitivesearchchatextensionconfiguration-strictness

// The configured top number of documents to feature for the configured query. Default is 5.
topNDocuments: 5, // https://learn.microsoft.com/javascript/api/@azure/openai/azurecognitivesearchchatextensionconfiguration?view=azure-node-preview#@azure-openai-azurecognitivesearchchatextensionconfiguration-topndocuments

// Give the model instructions about how it should behave and any context it should reference when generating a response. You can describe the assistant's personality and tell it how to format responses.
roleInformation: // https://learn.microsoft.com/javascript/api/@azure/openai/azurecognitivesearchchatextensionconfiguration?view=azure-node-preview#@azure-openai-azurecognitivesearchchatextensionconfiguration-roleinformation
//"You are an AI assistant that helps people find information.",
"You are an expert Site Reliability Engineer (SRE) and DevOps Engineer that helps people find information."
}
// Other available options: azure_cosmos_db, AzureMachineLearning, Pinecone, Elasticsearch
// https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/azure-machine-learning.md
// https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/pinecone.md
// https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/elasticsearch.md
// https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/ai-services/openai/references/cosmos-db.md

]
}
}
);

// Add the system's response to the conversation history
const systemResponse = chatResponse.choices[0].message.content;
appendConversationHistory("assistant", systemResponse, chatResponse);

console.info(`\n\ntoolCalls:\n${JSON.stringify(chatResponse.choices[0].message.toolCalls)}`);

console.info(`\n\nAI Response:\n${systemResponse}`);

//return res.json({ response: systemResponse });
return res.json(chatResponse);
} catch (error) {
console.error(error);
// return res.status(500).send('Error processing your request');
return res.status(500).json(error);
}
});

/**
* @openapi
* /v3/history:
* get:
* tags:
* - v3
* description: Retrieve Chat History
* responses:
* 200:
* description: Returns the OpenAI chat completion response.
* responseBody:
* content:
* application/json:
* schema:
* type: object
*/
app.get(`/v3/history`, async (req, res) => {
return res.json(rawConversationHistory);
});

/**
* @openapi
* /v3/clear:
* get:
* tags:
* - v3
* description: Clear Chat History
* responses:
* 200:
* description: Returns clear chat completion response.
*/
app.get(`/v3/clear`, async (req, res) => {
clearConversationHistory();
return res.status(200).send('Chat history cleared');
});
}
3 changes: 3 additions & 0 deletions app/nodejs/simple/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ app.use(express.static('static'))
* description: Call Azure OpenAI service to make Chat Completions.
* - name: v2
* description: Call Azure OpenAI service to make Chat Completions, also integrating Azure Search for additional data.
* - name: v3
* description: Call Azure OpenAI service to make Chat Completions, also integrating Azure Search for additional data, and a custom function for reading URL content from the web.
*/
require('./api/v1.js')(app)
require('./api/v2.js')(app)
require('./api/v3.js')(app)


// Add support for Swagger UI
Expand Down
5 changes: 4 additions & 1 deletion app/nodejs/simple/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
{
"dependencies": {
"@azure/openai": "^1.0.0-beta.11",
"axios": "^1.6.8",
"chai": "^4.4.1",
"chai-http": "^4.4.0",
"cheerio": "^1.0.0-rc.12",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"mocha": "^10.3.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0"
"swagger-ui-express": "^5.0.0",
"turndown": "^7.1.3"
},
"scripts": {
"test": "mocha test/*.js --exit"
Expand Down
2 changes: 1 addition & 1 deletion app/nodejs/simple/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ <h5><a href="https://build5nines.com" target="_blank"><img src="/images/build5ni
// ###################################################

// Configure the API version to use
const config_api_version = 'v2'; // "v1"
const config_api_version = 'v2'; //'v1';

// ###################################################

Expand Down

0 comments on commit 3ba94c5

Please sign in to comment.