Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

langchain[minor]: feat(embedding integration): Gradient AI #3475

Merged
merged 11 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api_refs/typedoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"./langchain/src/embeddings/minimax.ts",
"./langchain/src/embeddings/voyage.ts",
"./langchain/src/embeddings/llama_cpp.ts",
"./langchain/src/embeddings/gradient_ai.ts",
"./langchain/src/llms/load.ts",
"./langchain/src/llms/base.ts",
"./langchain/src/llms/openai.ts",
Expand Down
39 changes: 39 additions & 0 deletions docs/core_docs/docs/integrations/text_embedding/gradient_ai.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
sidebar_class_name: node-only
---

# Gradient AI

The `GradientEmbeddings` class uses the Gradient AI API to generate embeddings for a given text.

## Setup

You'll need to install the official Gradient Node SDK as a peer dependency:

```bash npm2yarn
npm i @gradientai/nodejs-sdk
```

You will need to set the following environment variables for using the Gradient AI API.

```
export GRADIENT_ACCESS_TOKEN=<YOUR_ACCESS_TOKEN>
export GRADIENT_WORKSPACE_ID=<YOUR_WORKSPACE_ID>
```

Alternatively, these can be set during the GradientAI Class instantiation as `gradientAccessKey` and `workspaceId` respectively.
For example:

```typescript
const model = new GradientEmbeddings({
gradientAccessKey: "My secret Access Token"
workspaceId: "My secret workspace id"
});
```

## Usage

import CodeBlock from "@theme/CodeBlock";
import GradientEmbeddingsExample from "@examples/embeddings/gradient_ai.ts";

<CodeBlock language="typescript">{GradientEmbeddingsExample}</CodeBlock>
7 changes: 7 additions & 0 deletions examples/src/embeddings/gradient_ai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { GradientEmbeddings } from "langchain/embeddings/gradient_ai";

const model = new GradientEmbeddings();
const res = await model.embedQuery(
"What would be a good company name a company that makes colorful socks?"
);
console.log({ res });
3 changes: 3 additions & 0 deletions langchain/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ embeddings/voyage.d.ts
embeddings/llama_cpp.cjs
embeddings/llama_cpp.js
embeddings/llama_cpp.d.ts
embeddings/gradient_ai.cjs
embeddings/gradient_ai.js
embeddings/gradient_ai.d.ts
llms/load.cjs
llms/load.js
llms/load.d.ts
Expand Down
8 changes: 8 additions & 0 deletions langchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
"embeddings/llama_cpp.cjs",
"embeddings/llama_cpp.js",
"embeddings/llama_cpp.d.ts",
"embeddings/gradient_ai.cjs",
"embeddings/gradient_ai.js",
"embeddings/gradient_ai.d.ts",
"llms/load.cjs",
"llms/load.js",
"llms/load.d.ts",
Expand Down Expand Up @@ -1698,6 +1701,11 @@
"import": "./embeddings/llama_cpp.js",
"require": "./embeddings/llama_cpp.cjs"
},
"./embeddings/gradient_ai": {
"types": "./embeddings/gradient_ai.d.ts",
"import": "./embeddings/gradient_ai.js",
"require": "./embeddings/gradient_ai.cjs"
},
"./llms/load": {
"types": "./llms/load.d.ts",
"import": "./llms/load.js",
Expand Down
2 changes: 2 additions & 0 deletions langchain/scripts/create-entrypoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const entrypoints = {
"embeddings/minimax": "embeddings/minimax",
"embeddings/voyage": "embeddings/voyage",
"embeddings/llama_cpp": "embeddings/llama_cpp",
"embeddings/gradient_ai": "embeddings/gradient_ai",
// llms
"llms/load": "llms/load",
"llms/base": "llms/base",
Expand Down Expand Up @@ -364,6 +365,7 @@ const requiresOptionalDependency = [
"embeddings/hf",
"embeddings/hf_transformers",
"embeddings/llama_cpp",
"embeddings/gradient_ai",
"llms/load",
"llms/cohere",
"llms/googlevertexai",
Expand Down
117 changes: 117 additions & 0 deletions langchain/src/embeddings/gradient_ai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Gradient } from "@gradientai/nodejs-sdk";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds a new feature that requires an environment variable to be set. Please review the code changes related to accessing the environment variable.

import { getEnvironmentVariable } from "../util/env.js";
import { chunkArray } from "../util/chunk.js";
import { Embeddings, EmbeddingsParams } from "./base.js";

/**
* Interface for GradientEmbeddings parameters. Extends EmbeddingsParams and
* defines additional parameters specific to the GradientEmbeddings class.
*/
export interface GradientEmbeddingsParams extends EmbeddingsParams {
/**
* Gradient AI Access Token.
* Provide Access Token if you do not wish to automatically pull from env.
*/
gradientAccessKey?: string;
/**
* Gradient Workspace Id.
* Provide workspace id if you do not wish to automatically pull from env.
*/
workspaceId?: string;
}

/**
* Class for generating embeddings using the Gradient AI's API. Extends the
* Embeddings class and implements GradientEmbeddingsParams and
*/
export class GradientEmbeddings
extends Embeddings
implements GradientEmbeddingsParams
{
gradientAccessKey?: string;

workspaceId?: string;

batchSize = 128;

model: any;

constructor(fields: GradientEmbeddingsParams) {
super(fields);

this.gradientAccessKey =
fields?.gradientAccessKey ??
getEnvironmentVariable("GRADIENT_ACCESS_TOKEN");
this.workspaceId =
fields?.workspaceId ?? getEnvironmentVariable("GRADIENT_WORKSPACE_ID");

if (!this.gradientAccessKey) {
throw new Error("Missing Gradient AI Access Token");
}

if (!this.workspaceId) {
throw new Error("Missing Gradient AI Workspace ID");
}
}

/**
* Method to generate embeddings for an array of documents. Splits the
* documents into batches and makes requests to the Gradient API to generate
* embeddings.
* @param texts Array of documents to generate embeddings for.
* @returns Promise that resolves to a 2D array of embeddings for each document.
*/
async embedDocuments(texts: string[]): Promise<number[][]> {
await this.setModel();

const mappedTexts = texts.map((text) => ({ input: text }));

const batches = chunkArray(mappedTexts, this.batchSize);

const batchRequests = batches.map((batch) =>
this.caller.call(async () =>
this.model.generateEmbeddings({
inputs: batch,
})
)
);
const batchResponses = await Promise.all(batchRequests);

const embeddings: number[][] = [];
for (let i = 0; i < batchResponses.length; i += 1) {
const batch = batches[i];
const { embeddings: batchResponse } = batchResponses[i];
for (let j = 0; j < batch.length; j += 1) {
embeddings.push(batchResponse[j].embedding);
}
}
return embeddings;
}

/**
* Method to generate an embedding for a single document. Calls the
* embedDocuments method with the document as the input.
* @param text Document to generate an embedding for.
* @returns Promise that resolves to an embedding for the document.
*/
async embedQuery(text: string): Promise<number[]> {
const data = await this.embedDocuments([text]);
return data[0];
}

/**
* Method to set the model to use for generating embeddings.
* @sets the class' `model` value to that of the retrieved Embeddings Model.
*/
async setModel() {
if (this.model) return;
chasemcdo marked this conversation as resolved.
Show resolved Hide resolved

const gradient = new Gradient({
accessToken: this.gradientAccessKey,
workspaceId: this.workspaceId,
});
this.model = await gradient.getEmbeddingsModel({
slug: "bge-large",
});
}
}
1 change: 1 addition & 0 deletions langchain/src/load/import_constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const optionalImportEntrypoints = [
"langchain/embeddings/googlevertexai",
"langchain/embeddings/googlepalm",
"langchain/embeddings/llama_cpp",
"langchain/embeddings/gradient_ai",
"langchain/llms/load",
"langchain/llms/cohere",
"langchain/llms/hf",
Expand Down
3 changes: 3 additions & 0 deletions langchain/src/load/import_type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export interface OptionalImportMap {
"langchain/embeddings/llama_cpp"?:
| typeof import("../embeddings/llama_cpp.js")
| Promise<typeof import("../embeddings/llama_cpp.js")>;
"langchain/embeddings/gradient_ai"?:
| typeof import("../embeddings/gradient_ai.js")
| Promise<typeof import("../embeddings/gradient_ai.js")>;
"langchain/llms/load"?:
| typeof import("../llms/load.js")
| Promise<typeof import("../llms/load.js")>;
Expand Down