LibreChat/api/server/services/Runs/methods.js
Danny Avila 5f2d1c5dc9
👁️ feat: Azure Mistral OCR Strategy (#7888)
* 👁️ feat: Add Azure Mistral OCR strategy and endpoint integration

This commit introduces a new OCR strategy named 'azure_mistral_ocr', allowing the use of a Mistral OCR endpoint deployed on Azure. The configuration, schemas, and file upload strategies have been updated to support this integration, enabling seamless OCR processing via Azure-hosted Mistral services.

* 🗑️ chore: Clean up .gitignore by removing commented-out uncommon directory name

* chore: remove unused vars

* refactor: Move createAxiosInstance to packages/api/utils and update imports

- Removed the createAxiosInstance function from the config module and relocated it to a new utils module for better organization.
- Updated import paths in relevant files to reflect the new location of createAxiosInstance.
- Added tests for createAxiosInstance to ensure proper functionality and proxy configuration handling.

* chore: move axios helpers to packages/api

- Added logAxiosError function to @librechat/api for centralized error logging.
- Updated imports across various files to use the new logAxiosError function.
- Removed the old axios.js utility file as it is no longer needed.

* chore: Update Jest moduleNameMapper for improved path resolution

- Added a new mapping for '~/' to resolve module paths in Jest configuration, enhancing import handling for the project.

* feat: Implement Mistral OCR API integration in TS

* chore: Update MistralOCR tests based on new imports

* fix: Enhance MistralOCR configuration handling and tests

- Introduced helper functions for resolving configuration values from environment variables or hardcoded settings.
- Updated the uploadMistralOCR and uploadAzureMistralOCR functions to utilize the new configuration resolution logic.
- Improved test cases to ensure correct behavior when mixing environment variables and hardcoded values.
- Mocked file upload and signed URL responses in tests to validate functionality without external dependencies.

* feat: Enhance MistralOCR functionality with improved configuration and error handling

- Introduced helper functions for loading authentication configuration and resolving values from environment variables.
- Updated uploadMistralOCR and uploadAzureMistralOCR functions to utilize the new configuration logic.
- Added utility functions for processing OCR results and creating error messages.
- Improved document type determination and result aggregation for better OCR processing.

* refactor: Reorganize OCR type imports in Mistral CRUD file

- Moved OCRResult, OCRResultPage, and OCRImage imports to a more logical grouping for better readability and maintainability.

* feat: Add file exports to API and create files index

* chore: Update OCR types for enhanced structure and clarity

- Redesigned OCRImage interface to include mandatory fields and improved naming conventions.
- Added PageDimensions interface for better representation of page metrics.
- Updated OCRResultPage to include dimensions and mandatory images array.
- Refined OCRResult to include document annotation and usage information.

* refactor: use TS counterpart of uploadOCR methods

* ci: Update MistralOCR tests to reflect new OCR result structure

* chore: Bump version of @librechat/api to 1.2.3 in package.json and package-lock.json

* chore: Update CONFIG_VERSION to 1.2.8

* chore: remove unused sendEvent function from config module (now imported from '@librechat/api')

* chore: remove MistralOCR service files and tests (now in '@librechat/api')

* ci: update logger import in ModelService tests to use @librechat/data-schemas

---------

Co-authored-by: arthurolivierfortin <arthurolivier.fortin@gmail.com>
2025-06-13 15:14:57 -04:00

62 lines
2 KiB
JavaScript

const axios = require('axios');
const { logAxiosError } = require('@librechat/api');
const { EModelEndpoint } = require('librechat-data-provider');
/**
* @typedef {Object} RetrieveOptions
* @property {string} thread_id - The ID of the thread to retrieve.
* @property {string} run_id - The ID of the run to retrieve.
* @property {number} [timeout] - Optional timeout for the API call.
* @property {number} [maxRetries] - TODO: not yet implemented; Optional maximum number of retries for the API call.
* @property {OpenAIClient} openai - Configuration and credentials for OpenAI API access.
*/
/**
* Asynchronously retrieves data from an API endpoint based on provided thread and run IDs.
*
* @param {RetrieveOptions} options - The options for the retrieve operation.
* @returns {Promise<Object>} The data retrieved from the API.
*/
async function retrieveRun({ thread_id, run_id, timeout, openai }) {
const { apiKey, baseURL, httpAgent, organization } = openai;
let url = `${baseURL}/threads/${thread_id}/runs/${run_id}`;
let headers = {
Authorization: `Bearer ${apiKey}`,
'OpenAI-Beta': 'assistants=v1',
};
if (organization) {
headers['OpenAI-Organization'] = organization;
}
/** @type {TAzureConfig | undefined} */
const azureConfig = openai.req.app.locals[EModelEndpoint.azureOpenAI];
if (azureConfig && azureConfig.assistants) {
delete headers.Authorization;
headers = { ...headers, ...openai._options.defaultHeaders };
const queryParams = new URLSearchParams(openai._options.defaultQuery).toString();
url = `${url}?${queryParams}`;
}
try {
const axiosConfig = {
headers: headers,
timeout: timeout,
};
if (httpAgent) {
axiosConfig.httpAgent = httpAgent;
axiosConfig.httpsAgent = httpAgent;
}
const response = await axios.get(url, axiosConfig);
return response.data;
} catch (error) {
const message = '[retrieveRun] Failed to retrieve run data:';
throw new Error(logAxiosError({ message, error }));
}
}
module.exports = { retrieveRun };