Skip to content

Commit

Permalink
add ultility and merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
tomfrenken committed Sep 16, 2024
1 parent 3e97d8f commit a62dba0
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 24 deletions.
6 changes: 1 addition & 5 deletions packages/langchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@ $ npm install @langchain/openai // if you want to use OpenAI models
## Pre-requisites

- [Enable the AI Core service in BTP](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/initial-setup).
- Project configured with Node.js v20 or higher and native ESM support enabled.
- For testing your application locally:
- Download a service key for your AI Core service instance.
- Create a `.env` file in the sample-code directory.
- Add an entry `AICORE_SERVICE_KEY='<content-of-service-key>'`.
- Ensure the project is configured with Node.js v20 or higher, along with native ESM support.

## Usage

Expand Down
2 changes: 1 addition & 1 deletion packages/langchain/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { OpenAiChatClient, OpenAiEmbeddingClient } from './openai/index.js';
export { AzureOpenAiChatClient, AzureOpenAiEmbeddingClient } from './openai/index.js';
export type {
OpenAiChatModelInput,
OpenAiEmbeddingInput,
Expand Down
13 changes: 4 additions & 9 deletions packages/langchain/src/openai/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,26 @@ import { BaseMessage } from '@langchain/core/messages';
import type { ChatResult } from '@langchain/core/outputs';
import { AzureChatOpenAI, AzureOpenAI } from '@langchain/openai';
import { OpenAiChatClient as OpenAiChatClientBase } from '@sap-ai-sdk/foundation-models';
import { mapLangchainToAiClient, mapResponseToChatResult } from './util.js';
import { mapLangchainToAiClient, mapResponseToChatResult, toArrayOrUndefined } from './util.js';
import type { OpenAiChatModelInput, OpenAiChatCallOptions } from './types.js';

/**
* OpenAI Language Model Wrapper to generate texts.
*/
export class OpenAiChatClient extends AzureChatOpenAI {
export class AzureOpenAiChatClient extends AzureChatOpenAI {
declare CallOptions: OpenAiChatCallOptions;
private openAiChatClient: OpenAiChatClientBase;

constructor(fields: OpenAiChatModelInput) {
const defaultValues = new AzureOpenAI({ apiKey: 'dummy' });
const stop = fields.stop
? Array.isArray(fields.stop)
? fields.stop
: [fields.stop]
: defaultValues.stop;
const stop = toArrayOrUndefined<string>(fields.stop);
super({
...defaultValues,
...fields,
stop,
// overrides the apikey values as they are not applicable for BTP
azureOpenAIApiKey: undefined,
openAIApiKey: undefined,
apiKey: 'dummy'
openAIApiKey: undefined
});

this.openAiChatClient = new OpenAiChatClientBase({ ...fields });
Expand Down
5 changes: 2 additions & 3 deletions packages/langchain/src/openai/embedding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { OpenAiEmbeddingInput } from './types.js';
/**
* OpenAI GPT Language Model Wrapper to embed texts.
*/
export class OpenAiEmbeddingClient extends AzureOpenAIEmbeddings {
export class AzureOpenAiEmbeddingClient extends AzureOpenAIEmbeddings {
private btpOpenAIClient: OpenAiEmbeddingClientBase;

constructor(fields: OpenAiEmbeddingInput) {
Expand Down Expand Up @@ -45,9 +45,8 @@ export class OpenAiEmbeddingClient extends AzureOpenAIEmbeddings {
private async createEmbedding(
query: OpenAiEmbeddingParameters
): Promise<OpenAiEmbeddingOutput> {
const res = await this.caller.callWithOptions({}, () =>
return this.caller.callWithOptions({}, () =>
this.btpOpenAIClient.run(query)
);
return res;
}
}
4 changes: 2 additions & 2 deletions packages/langchain/src/openai/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
parseMockResponse
} from '../../../../test-util/mock-http.js';
import { mapResponseToChatResult } from './util.js';
import { OpenAiChatClient } from './chat.js';
import { AzureOpenAiChatClient } from './chat.js';

const openAiMockResponse = parseMockResponse<OpenAiChatCompletionOutput>(
'foundation-models',
Expand Down Expand Up @@ -98,7 +98,7 @@ describe('Mapping Functions', () => {
chatCompletionEndpoint
);

const client = new OpenAiChatClient({ deploymentId: '1234' });
const client = new AzureOpenAiChatClient({ deploymentId: '1234' });
const runSpy = jest.spyOn(OpenAiChatClientBase.prototype, 'run');
await client.generate([[langchainPrompt]]);
expect(runSpy).toHaveBeenCalledWith(request);
Expand Down
20 changes: 16 additions & 4 deletions packages/langchain/src/openai/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
OpenAiChatCompletionParameters
} from '@sap-ai-sdk/foundation-models';
import { zodToJsonSchema } from 'zod-to-json-schema';
import { OpenAiChatClient } from './chat.js';
import { AzureOpenAiChatClient } from './chat.js';
import { OpenAiChatCallOptions } from './types.js';

/**
Expand Down Expand Up @@ -143,6 +143,18 @@ export function mapBaseMessageToOpenAiChatMessage(
} as OpenAiChatMessage;
}

/**
* Converts a value to an array or returns undefined.
* @param value - The value to convert.
* @returns The value as an array, undefined if the input is falsy, or the original array if input is already an array.
*/
export function toArrayOrUndefined<T>(value?: T | T[]): T[] | undefined {
if(value === undefined) {
return undefined;
}
return Array.isArray(value) ? value : [value];
}

/**
* Checks if a given array is a structured tool array.
* @param tools - The array to check.
Expand All @@ -159,15 +171,15 @@ export function isStructuredToolArray(
}

/**
* Maps the langchain's input interface to our own client's input interface
* Maps Langchain's input interface to our own client's input interface
* @param client The Langchain OpenAI client
* @param options The Langchain call options
* @param messages The messages to be send
* @returns A AI SDK compatibile request
* @returns An AI SDK compatibile request
* @internal
*/
export function mapLangchainToAiClient(
client: OpenAiChatClient,
client: AzureOpenAiChatClient,
options: OpenAiChatCallOptions,
messages: BaseMessage[]
): OpenAiChatCompletionParameters {
Expand Down

0 comments on commit a62dba0

Please sign in to comment.