All files / api/src/ai-providers/azure-ai-foundry chat-complete.ts

100% Statements 88/88
100% Branches 9/9
100% Functions 3/3
100% Lines 88/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104        1x       1x         1x     1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 1x 2x 2x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x 51x 51x 51x 7x 7x 7x 7x 4x 4x   3x 7x 51x 51x  
import type {
  AIProviderFunctionConfig,
  ResponseTransformFunction,
} from '@shared/types/ai-providers/config';
import {
  type ChatCompletionRequestBody,
  ChatCompletionResponseBody,
} from '@shared/types/api/routes/chat-completions-api';
import {
  type ChatCompletionMessage,
  ChatCompletionMessageRole,
} from '@shared/types/api/routes/shared/messages';
import type { AIProvider } from '@shared/types/constants';
import { openAIErrorResponseTransform } from '../openai/utils';
 
// TODOS: this configuration does not enforce the maximum token limit for the input parameter. If you want to enforce this, you might need to add a custom validation function or a max property to the ParameterConfig interface, and then use it in the input configuration. However, this might be complex because the token count is not a simple length check, but depends on the specific tokenization method used by the model.
export const azureAIInferenceChatCompleteConfig: AIProviderFunctionConfig = {
  model: {
    param: 'model',
    required: false,
  },
  messages: {
    param: 'messages',
    default: '',
    transform: (
      saRequestData: ChatCompletionRequestBody,
    ): ChatCompletionMessage[] | undefined => {
      if (!saRequestData.messages) return undefined;
      return saRequestData.messages.map((message) => {
        if (message.role === ChatCompletionMessageRole.DEVELOPER)
          return { ...message, role: ChatCompletionMessageRole.SYSTEM };
        return message;
      });
    },
  },
  max_tokens: {
    param: 'max_tokens',
    default: 100,
    min: 0,
  },
  max_completion_tokens: {
    param: 'max_tokens',
    default: 100,
    min: 0,
  },
  temperature: {
    param: 'temperature',
    default: 1,
    min: 0,
    max: 2,
  },
  top_p: {
    param: 'top_p',
    default: 1,
    min: 0,
    max: 1,
  },
  stream: {
    param: 'stream',
    default: false,
  },
  stop: {
    param: 'stop',
  },
  presence_penalty: {
    param: 'presence_penalty',
    min: -2,
    max: 2,
  },
  frequency_penalty: {
    param: 'frequency_penalty',
    min: -2,
    max: 2,
  },
  user: {
    param: 'user',
  },
  tools: {
    param: 'tools',
  },
  tool_choice: {
    param: 'tool_choice',
  },
  response_format: {
    param: 'response_format',
  },
};
 
export const azureAIInferenceChatCompleteResponseTransform = (
  provider: AIProvider,
): ResponseTransformFunction => {
  const transformer: ResponseTransformFunction = (
    aiProviderResponseBody,
    aiProviderResponseStatus,
  ) => {
    if (aiProviderResponseStatus !== 200 && 'error' in aiProviderResponseBody) {
      return openAIErrorResponseTransform(aiProviderResponseBody, provider);
    }
 
    return ChatCompletionResponseBody.parse(aiProviderResponseBody);
  };
  return transformer;
};