Skip to content

Commit 71ab5dc

Browse files
author
tomfrenken
committed
add mapping functions
1 parent b08589c commit 71ab5dc

File tree

7 files changed

+240
-112
lines changed

7 files changed

+240
-112
lines changed

packages/langchain/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@sap-ai-sdk/foundation-models": "workspace:^",
3232
"@sap-ai-sdk/orchestration": "workspace:^",
3333
"@sap-cloud-sdk/connectivity": "^3.26.1",
34+
"@sap-cloud-sdk/resilience": "^3.26.1",
3435
"uuid": "^11.1.0",
3536
"@langchain/core": "0.3.40",
3637
"zod-to-json-schema": "^3.24.1"
Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
11
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
22
import { OrchestrationClient as OrchestrationClientBase } from '@sap-ai-sdk/orchestration';
33
import { AsyncCaller } from '@langchain/core/utils/async_caller';
4-
import { mapLangchainMessagesToOrchestrationMessages, mapOutputToChatResult } from './util.js';
4+
import { resilience } from '@sap-cloud-sdk/resilience';
5+
import {
6+
isTemplate,
7+
mapLangchainMessagesToOrchestrationMessages,
8+
mapOutputToChatResult
9+
} from './util.js';
10+
import type { CustomRequestConfig } from '@sap-ai-sdk/core';
511
import type { OrchestrationMessageChunk } from './orchestration-message-chunk.js';
612
import type { ChatResult } from '@langchain/core/outputs';
713
import type { OrchestrationModuleConfig } from '@sap-ai-sdk/orchestration';
814
import type { BaseChatModelParams } from '@langchain/core/language_models/chat_models';
915
import type { ResourceGroupConfig } from '@sap-ai-sdk/ai-api';
1016
import type { BaseMessage } from '@langchain/core/messages';
1117
import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
12-
import type {
13-
OrchestrationCallOptions
14-
} from './types.js';
18+
import type { OrchestrationCallOptions } from './types.js';
1519
import type { HttpDestinationOrFetchOptions } from '@sap-cloud-sdk/connectivity';
1620

1721
// TODO: Update all docs
1822

1923
/**
2024
* LangChain chat client for Azure OpenAI consumption on SAP BTP.
2125
*/
22-
export class OrchestrationClient extends BaseChatModel<OrchestrationCallOptions, OrchestrationMessageChunk> {
26+
export class OrchestrationClient extends BaseChatModel<
27+
OrchestrationCallOptions,
28+
OrchestrationMessageChunk
29+
> {
2330
constructor(
2431
// Omit streaming until supported
2532
public orchestrationConfig: Omit<OrchestrationModuleConfig, 'streaming'>,
2633
public langchainOptions: BaseChatModelParams = {},
2734
public deploymentConfig?: ResourceGroupConfig,
28-
public destination?: HttpDestinationOrFetchOptions,
35+
public destination?: HttpDestinationOrFetchOptions
2936
) {
3037
super(langchainOptions);
3138
}
@@ -36,12 +43,12 @@ export class OrchestrationClient extends BaseChatModel<OrchestrationCallOptions,
3643

3744
/**
3845
* Decisions:
39-
* bind only supports ParsedCallOptions, we don't support arbitrary LLM options, only tool calls & default BaseLanguageModelCallOptions, e.g. stop
40-
* this aligns with other vendors' client designs (e.g. openai, google)
46+
* bind only supports ParsedCallOptions, we don't support arbitrary LLM options, only tool calls & default BaseLanguageModelCallOptions, e.g. stop
47+
* this aligns with other vendors' client designs (e.g. openai, google)
4148
* top of the array (array[array.length - 1]) contains the current message, everything before then is history.
4249
* Module results are part of our own message type, which extends AI Message to work with all other langchain functionality.
4350
*
44-
* For timeout, we need to apply our own middleware, it is not handled by langchain.
51+
* For timeout, we need to apply our own middleware, it is not handled by langchain. ✅.
4552
*/
4653

4754
override async _generate(
@@ -50,29 +57,44 @@ export class OrchestrationClient extends BaseChatModel<OrchestrationCallOptions,
5057
runManager?: CallbackManagerForLLMRun
5158
): Promise<ChatResult> {
5259
let caller = this.caller;
53-
if(options.maxConcurrency) {
54-
const { maxConcurrency, maxRetries, onFailedAttempt } = this.langchainOptions;
55-
caller = new AsyncCaller(
56-
{ maxConcurrency: maxConcurrency ?? options.maxConcurrency,
57-
maxRetries,
58-
onFailedAttempt
59-
}
60-
);
60+
if (options.maxConcurrency) {
61+
const { maxConcurrency, maxRetries, onFailedAttempt } =
62+
this.langchainOptions;
63+
caller = new AsyncCaller({
64+
maxConcurrency: maxConcurrency ?? options.maxConcurrency,
65+
maxRetries,
66+
onFailedAttempt
67+
});
6168
}
6269
const res = await caller.callWithOptions(
6370
{
6471
signal: options.signal
6572
},
6673
() => {
67-
// consider this.tools & this.stop property, merge it ith template orchestration config
68-
const orchestrationClient = new OrchestrationClientBase(this.orchestrationConfig, this.deploymentConfig, this.destination);
69-
const { messageHistory, inputParams } = mapLangchainMessagesToOrchestrationMessages(messages);
70-
return orchestrationClient.chatCompletion({
71-
// how to handle tools here? doesn't really exist as input in orchestration as message history
72-
// make template a call option, to merge it ??
73-
messagesHistory,
74-
inputParams
75-
}, options.customRequestConfig);
74+
// consider this.tools & this.stop property, merge it with template orchestration config
75+
const { inputParams } = options;
76+
const mergedOrchestrationConfig =
77+
this.mergeOrchestrationConfig(options);
78+
const orchestrationClient = new OrchestrationClientBase(
79+
mergedOrchestrationConfig,
80+
this.deploymentConfig,
81+
this.destination
82+
);
83+
const messagesHistory =
84+
mapLangchainMessagesToOrchestrationMessages(messages);
85+
const customRequestConfig: CustomRequestConfig = {
86+
...options.customRequestConfig,
87+
middleware: resilience({ timeout: options.timeout })
88+
};
89+
return orchestrationClient.chatCompletion(
90+
{
91+
// how to handle tools here? doesn't really exist as input in orchestration as message history
92+
// make template a call option, to merge it ??
93+
messagesHistory,
94+
inputParams
95+
},
96+
customRequestConfig
97+
);
7698
}
7799
);
78100

@@ -85,5 +107,35 @@ export class OrchestrationClient extends BaseChatModel<OrchestrationCallOptions,
85107

86108
return mapOutputToChatResult(res.data);
87109
}
88-
}
89110

111+
private mergeOrchestrationConfig(
112+
options: typeof this.ParsedCallOptions
113+
): OrchestrationModuleConfig {
114+
const { tools = [], stop = [] } = options;
115+
return {
116+
...this.orchestrationConfig,
117+
llm: {
118+
...this.orchestrationConfig.llm,
119+
model_params: {
120+
...this.orchestrationConfig.llm.model_params,
121+
...(stop.length && {
122+
stop: [
123+
...(this.orchestrationConfig.llm.model_params?.stop || []),
124+
...stop
125+
]
126+
})
127+
}
128+
},
129+
templating: {
130+
...this.orchestrationConfig.templating,
131+
...(isTemplate(this.orchestrationConfig.templating) &&
132+
tools.length && {
133+
tools: [
134+
...(this.orchestrationConfig.templating.tools || []),
135+
...tools
136+
]
137+
})
138+
}
139+
};
140+
}
141+
}

packages/langchain/src/orchestration/orchestration-message-chunk.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ import type { ModuleResults } from '@sap-ai-sdk/orchestration';
66
* TODO: Add docs.
77
*/
88
export class OrchestrationMessageChunk extends AIMessageChunk {
9-
module_results: ModuleResults;
10-
request_id: string;
11-
constructor(fields: string | AIMessageChunkFields, module_results: ModuleResults, request_id: string) {
12-
super(fields);
13-
this.module_results = module_results;
14-
this.request_id = request_id;
15-
}
9+
module_results: ModuleResults;
10+
request_id: string;
11+
constructor(
12+
fields: string | AIMessageChunkFields,
13+
module_results: ModuleResults,
14+
request_id: string
15+
) {
16+
super(fields);
17+
this.module_results = module_results;
18+
this.request_id = request_id;
1619
}
20+
}

packages/langchain/src/orchestration/orchestration-message.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ import type { ModuleResults } from '@sap-ai-sdk/orchestration';
66
* TODO: Add docs.
77
*/
88
export class OrchestrationMessage extends AIMessage {
9-
module_results: ModuleResults;
10-
request_id: string;
11-
constructor(fields: string | AIMessageFields, module_results: ModuleResults, request_id: string) {
12-
super(fields);
13-
this.module_results = module_results;
14-
this.request_id = request_id;
15-
}
9+
module_results: ModuleResults;
10+
request_id: string;
11+
constructor(
12+
fields: string | AIMessageFields,
13+
module_results: ModuleResults,
14+
request_id: string
15+
) {
16+
super(fields);
17+
this.module_results = module_results;
18+
this.request_id = request_id;
19+
}
1620
}
Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,15 @@
1-
import type { Template } from '@sap-ai-sdk/orchestration';
2-
import type {
3-
BaseChatModelCallOptions
4-
} from '@langchain/core/language_models/chat_models';
5-
import type {
6-
AzureOpenAiCreateChatCompletionRequest
7-
} from '@sap-ai-sdk/foundation-models';
1+
import type { Prompt, Template } from '@sap-ai-sdk/orchestration';
2+
import type { BaseChatModelCallOptions } from '@langchain/core/language_models/chat_models';
83
import type { CustomRequestConfig } from '@sap-ai-sdk/core';
94

10-
/**
11-
* Call options for the {@link AzureOpenAiChatClient}.
12-
*/
13-
export type AzureOpenAiChatCallOptions = BaseChatModelCallOptions &
14-
Pick<
15-
AzureOpenAiCreateChatCompletionRequest,
16-
| 'data_sources'
17-
| 'n'
18-
| 'seed'
19-
| 'logprobs'
20-
| 'top_logprobs'
21-
| 'response_format'
22-
| 'tool_choice'
23-
| 'functions'
24-
| 'function_call'
25-
| 'tools'
26-
> & {
27-
requestConfig?: CustomRequestConfig;
28-
};
29-
305
/**
316
* TODO: Add docs.
327
*/
338
export type OrchestrationCallOptions = Pick<
349
BaseChatModelCallOptions,
35-
| 'stop'
36-
| 'signal'
37-
| 'maxConcurrency'
38-
| 'timeout'
39-
> & {
40-
customRequestConfig?: CustomRequestConfig;
41-
tools?: Template['tools'];
42-
};
43-
10+
'stop' | 'signal' | 'maxConcurrency' | 'timeout'
11+
> & {
12+
customRequestConfig?: CustomRequestConfig;
13+
tools?: Template['tools'];
14+
inputParams?: Prompt['inputParams'];
15+
};

0 commit comments

Comments
 (0)