@sap-ai-sdk/langchain
Version:
SAP Cloud SDK for AI is the official Software Development Kit (SDK) for **SAP AI Core**, **SAP Generative AI Hub**, and **Orchestration Service**.
92 lines • 3.73 kB
JavaScript
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
import { OrchestrationClient as OrchestrationClientBase } from '@sap-ai-sdk/orchestration';
import { isTemplate, mapLangchainMessagesToOrchestrationMessages, mapOutputToChatResult } from './util.js';
function isInputFilteringError(error) {
return (error.cause?.status === 400 &&
error.cause?.response?.data?.location?.includes('Input Filter'));
}
/**
* The Orchestration client.
*/
export class OrchestrationClient extends BaseChatModel {
orchestrationConfig;
langchainOptions;
deploymentConfig;
destination;
constructor(
// TODO: Omit streaming until supported
orchestrationConfig, langchainOptions = {}, deploymentConfig, destination) {
// Avoid retry if the error is due to input filtering
const { onFailedAttempt } = langchainOptions;
langchainOptions.onFailedAttempt = error => {
if (isInputFilteringError(error)) {
throw error;
}
onFailedAttempt?.(error);
};
super(langchainOptions);
this.orchestrationConfig = orchestrationConfig;
this.langchainOptions = langchainOptions;
this.deploymentConfig = deploymentConfig;
this.destination = destination;
}
_llmType() {
return 'orchestration';
}
/**
* Create a new runnable sequence that runs each individual runnable in series,
* piping the output of one runnable into another runnable or runnable-like.
* @param coerceable - A runnable, function, or object whose values are functions or runnables.
* @returns A new runnable sequence.
*/
pipe(coerceable) {
return super.pipe(coerceable);
}
async _generate(messages, options, runManager) {
const res = await this.caller.callWithOptions({
signal: options.signal
}, () => {
const { inputParams, customRequestConfig } = options;
const mergedOrchestrationConfig = this.mergeOrchestrationConfig(options);
const orchestrationClient = new OrchestrationClientBase(mergedOrchestrationConfig, this.deploymentConfig, this.destination);
const messagesHistory = mapLangchainMessagesToOrchestrationMessages(messages);
return orchestrationClient.chatCompletion({
messagesHistory,
inputParams
}, customRequestConfig);
});
const content = res.getContent();
// TODO: Add streaming as soon as we support it
await runManager?.handleLLMNewToken(typeof content === 'string' ? content : '');
return mapOutputToChatResult(res.data);
}
mergeOrchestrationConfig(options) {
const { tools = [], stop = [] } = options;
return {
...this.orchestrationConfig,
llm: {
...this.orchestrationConfig.llm,
model_params: {
...this.orchestrationConfig.llm.model_params,
...(stop.length && {
stop: [
...(this.orchestrationConfig.llm.model_params?.stop || []),
...stop
]
})
}
},
templating: {
...this.orchestrationConfig.templating,
...(isTemplate(this.orchestrationConfig.templating) &&
tools.length && {
tools: [
...(this.orchestrationConfig.templating.tools || []),
...tools
]
})
}
};
}
}
//# sourceMappingURL=client.js.map