Compare commits

...

6 Commits

Author SHA1 Message Date
github-actions[bot] 2afcbe6587 Release 0.5.20 (#1132)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-28 10:43:26 +07:00
Marcus Schiesser 22ff486fbe fix: Add tiktoken WASM to withLlamaIndex (#1134)
Co-authored-by: Thuc Pham <51660321+thucpn@users.noreply.github.com>
2024-08-28 10:39:14 +07:00
Thuc Pham eed0b0415d fix: use metadata mode LLM for generating context (#1133)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
2024-08-23 22:56:18 +07:00
Sebastian van Gerwen d9d6c56ed5 pgvectorstore support new conditions and operations (#1131)
Co-authored-by: Sebastian van Gerwen <svangerwen@invertigro.com>
Co-authored-by: Marcus Schiesser <marcus.schiesser@googlemail.com>
2024-08-23 14:40:39 +07:00
github-actions[bot] f99a237093 Release 0.5.19 (#1128)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-19 14:04:47 +07:00
Thuc Pham fcbf18344c feat: implement llamacloud file service (#1125) 2024-08-19 14:01:41 +07:00
27 changed files with 416 additions and 20 deletions
+16
View File
@@ -1,5 +1,21 @@
# docs
## 0.0.61
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.0.60
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.0.59
### Patch Changes
+10 -3
View File
@@ -6,10 +6,17 @@ sidebar_position: 2
We support Node.JS versions 18, 20 and 22, with experimental support for Deno, Bun and Vercel Edge functions.
## NextJS App Router
## NextJS
If you're using NextJS App Router route handlers/serverless functions, you'll need to use the NodeJS mode:
If you're using NextJS you'll need to add `withLlamaIndex` to your `next.config.js` file. This will add the necessary configuration for included 3rd-party libraries to your build:
```js
export const runtime = "nodejs"; // default
// next.config.js
const withLlamaIndex = require("llamaindex/next");
module.exports = withLlamaIndex({
// your next.js config
});
```
For details, check the latest [withLlamaIndex](https://github.com/run-llama/LlamaIndexTS/blob/main/packages/llamaindex/src/next.ts) implementation.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "docs",
"version": "0.0.59",
"version": "0.0.61",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -1,5 +1,23 @@
# @llamaindex/autotool-02-next-example
## 0.1.45
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
- @llamaindex/autotool@2.0.1
## 0.1.44
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
- @llamaindex/autotool@2.0.1
## 0.1.43
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/autotool-02-next-example",
"private": true,
"version": "0.1.43",
"version": "0.1.45",
"scripts": {
"dev": "next dev",
"build": "next build",
+1 -1
View File
@@ -51,7 +51,7 @@
"unplugin": "^1.10.1"
},
"peerDependencies": {
"llamaindex": "^0.5.18",
"llamaindex": "^0.5.20",
"openai": "^4",
"typescript": "^4"
},
+16
View File
@@ -1,5 +1,21 @@
# @llamaindex/experimental
## 0.0.70
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.0.69
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.0.68
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/experimental",
"description": "Experimental package for LlamaIndexTS",
"version": "0.0.68",
"version": "0.0.70",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+14
View File
@@ -1,5 +1,19 @@
# llamaindex
## 0.5.20
### Patch Changes
- d9d6c56: Add support for MetadataFilters for PostgreSQL
- 22ff486: Add tiktoken WASM to withLlamaIndex
- eed0b04: fix: use LLM metadata mode for generating context of ContextChatEngine
## 0.5.19
### Patch Changes
- fcbf183: implement llamacloud file service
## 0.5.18
### Patch Changes
@@ -1,5 +1,21 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.54
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.0.53
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.0.52
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.52",
"version": "0.0.54",
"type": "module",
"private": true,
"scripts": {
@@ -1,5 +1,21 @@
# @llamaindex/next-agent-test
## 0.1.54
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.1.53
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.1.52
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.52",
"version": "0.1.54",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,21 @@
# test-edge-runtime
## 0.1.53
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.1.52
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.1.51
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.51",
"version": "0.1.53",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,21 @@
# @llamaindex/next-node-runtime
## 0.0.35
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.0.34
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.0.33
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-node-runtime-test",
"version": "0.0.33",
"version": "0.0.35",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,21 @@
# @llamaindex/waku-query-engine-test
## 0.0.54
### Patch Changes
- Updated dependencies [d9d6c56]
- Updated dependencies [22ff486]
- Updated dependencies [eed0b04]
- llamaindex@0.5.20
## 0.0.53
### Patch Changes
- Updated dependencies [fcbf183]
- llamaindex@0.5.19
## 0.0.52
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.52",
"version": "0.0.54",
"type": "module",
"private": true,
"scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "llamaindex",
"version": "0.5.18",
"version": "0.5.20",
"license": "MIT",
"type": "module",
"keywords": [
@@ -0,0 +1,99 @@
import {
FilesService,
PipelinesService,
ProjectsService,
} from "@llamaindex/cloud/api";
import { initService } from "./utils.js";
export class LLamaCloudFileService {
/**
* Get list of projects, each project contains a list of pipelines
*/
public static async getAllProjectsWithPipelines() {
initService();
try {
const projects = await ProjectsService.listProjectsApiV1ProjectsGet();
const pipelines =
await PipelinesService.searchPipelinesApiV1PipelinesGet();
return projects.map((project) => ({
...project,
pipelines: pipelines.filter((p) => p.project_id === project.id),
}));
} catch (error) {
console.error("Error listing projects and pipelines:", error);
return [];
}
}
/**
* Upload a file to a pipeline in LlamaCloud
*/
public static async addFileToPipeline(
projectId: string,
pipelineId: string,
uploadFile: File | Blob,
customMetadata: Record<string, any> = {},
) {
initService();
const file = await FilesService.uploadFileApiV1FilesPost({
projectId,
formData: {
upload_file: uploadFile,
},
});
const files = [
{
file_id: file.id,
custom_metadata: { file_id: file.id, ...customMetadata },
},
];
await PipelinesService.addFilesToPipelineApiV1PipelinesPipelineIdFilesPut({
pipelineId,
requestBody: files,
});
// Wait 2s for the file to be processed
const maxAttempts = 20;
let attempt = 0;
while (attempt < maxAttempts) {
const result =
await PipelinesService.getPipelineFileStatusApiV1PipelinesPipelineIdFilesFileIdStatusGet(
{
pipelineId,
fileId: file.id,
},
);
if (result.status === "ERROR") {
throw new Error(`File processing failed: ${JSON.stringify(result)}`);
}
if (result.status === "SUCCESS") {
// File is ingested - return the file id
return file.id;
}
attempt += 1;
await new Promise((resolve) => setTimeout(resolve, 100)); // Sleep for 100ms
}
throw new Error(
`File processing did not complete after ${maxAttempts} attempts.`,
);
}
/**
* Get download URL for a file in LlamaCloud
*/
public static async getFileUrl(pipelineId: string, filename: string) {
initService();
const allPipelineFiles =
await PipelinesService.listPipelineFilesApiV1PipelinesPipelineIdFilesGet({
pipelineId,
});
const file = allPipelineFiles.find((file) => file.name === filename);
if (!file?.file_id) return null;
const fileContent =
await FilesService.readFileContentApiV1FilesIdContentGet({
id: file.file_id,
projectId: file.project_id,
});
return fileContent.url;
}
}
+1
View File
@@ -1,4 +1,5 @@
export type { CloudConstructorParams } from "./constants.js";
export { LLamaCloudFileService } from "./LLamaCloudFileService.js";
export { LlamaCloudIndex } from "./LlamaCloudIndex.js";
export {
LlamaCloudRetriever,
@@ -4,7 +4,7 @@ import type {
MessageContent,
MessageType,
} from "@llamaindex/core/llms";
import { EngineResponse } from "@llamaindex/core/schema";
import { EngineResponse, MetadataMode } from "@llamaindex/core/schema";
import {
extractText,
streamConverter,
@@ -53,6 +53,7 @@ export class ContextChatEngine extends PromptMixin implements ChatEngine {
contextSystemPrompt: init?.contextSystemPrompt,
nodePostprocessors: init?.nodePostprocessors,
contextRole: init?.contextRole,
metadataMode: MetadataMode.LLM,
});
this.systemPrompt = init.systemPrompt;
}
@@ -1,5 +1,5 @@
import type { MessageContent, MessageType } from "@llamaindex/core/llms";
import { type NodeWithScore } from "@llamaindex/core/schema";
import { MetadataMode, type NodeWithScore } from "@llamaindex/core/schema";
import type { BaseNodePostprocessor } from "../../postprocessors/index.js";
import type { ContextSystemPrompt } from "../../Prompt.js";
import { defaultContextSystemPrompt } from "../../Prompt.js";
@@ -16,12 +16,14 @@ export class DefaultContextGenerator
contextSystemPrompt: ContextSystemPrompt;
nodePostprocessors: BaseNodePostprocessor[];
contextRole: MessageType;
metadataMode?: MetadataMode;
constructor(init: {
retriever: BaseRetriever;
contextSystemPrompt?: ContextSystemPrompt;
nodePostprocessors?: BaseNodePostprocessor[];
contextRole?: MessageType;
metadataMode?: MetadataMode;
}) {
super();
@@ -30,6 +32,7 @@ export class DefaultContextGenerator
init?.contextSystemPrompt ?? defaultContextSystemPrompt;
this.nodePostprocessors = init.nodePostprocessors || [];
this.contextRole = init.contextRole ?? "system";
this.metadataMode = init.metadataMode ?? MetadataMode.NONE;
}
protected _getPrompts(): { contextSystemPrompt: ContextSystemPrompt } {
@@ -75,6 +78,8 @@ export class DefaultContextGenerator
const content = await createMessageContent(
this.contextSystemPrompt,
nodes.map((r) => r.node),
undefined,
this.metadataMode,
);
return {
+7
View File
@@ -17,6 +17,13 @@
*/
export default function withLlamaIndex(config: any) {
config.experimental = config.experimental ?? {};
// copy tiktoken WASM files to the NextJS build
config.experimental.outputFileTracingIncludes =
config.experimental.outputFileTracingIncludes ?? {};
config.experimental.outputFileTracingIncludes["/**/*"] = [
"./node_modules/tiktoken/*.wasm",
];
// needed for transformers, see https://huggingface.co/docs/transformers.js/en/tutorials/next#step-2-install-and-configure-transformersjs
config.experimental.serverComponentsExternalPackages =
config.experimental.serverComponentsExternalPackages ?? [];
config.experimental.serverComponentsExternalPackages.push(
@@ -1,13 +1,19 @@
import type pg from "pg";
import {
FilterCondition,
FilterOperator,
VectorStoreBase,
type IEmbedModel,
type MetadataFilter,
type MetadataFilterValue,
type VectorStoreNoEmbedModel,
type VectorStoreQuery,
type VectorStoreQueryResult,
} from "./types.js";
import { escapeLikeString } from "./utils.js";
import type { BaseNode, Metadata } from "@llamaindex/core/schema";
import { Document, MetadataMode } from "@llamaindex/core/schema";
@@ -246,6 +252,120 @@ export class PGVectorStore
return Promise.resolve();
}
private toPostgresCondition(condition: `${FilterCondition}`) {
if (condition === FilterCondition.AND) {
return "AND";
}
if (condition === FilterCondition.OR) {
return "OR";
}
// fallback to AND
else {
return "AND";
}
}
private toPostgresOperator(operator: `${FilterOperator}`) {
if (operator === FilterOperator.EQ) {
return "=";
}
if (operator === FilterOperator.GT) {
return ">";
}
if (operator === FilterOperator.LT) {
return "<";
}
if (operator === FilterOperator.NE) {
return "!=";
}
if (operator === FilterOperator.GTE) {
return ">=";
}
if (operator === FilterOperator.LTE) {
return "<=";
}
if (operator === FilterOperator.IN) {
return "= ANY";
}
if (operator === FilterOperator.NIN) {
return "!= ANY";
}
if (operator === FilterOperator.CONTAINS) {
return "@>";
}
if (operator === FilterOperator.ANY) {
return "?|";
}
if (operator === FilterOperator.ALL) {
return "?&";
}
// fallback to "="
return "=";
}
private buildFilterClause(
filter: MetadataFilter,
paramIndex: number,
): {
clause: string;
param: string | string[] | number | number[] | undefined;
} {
if (
filter.operator === FilterOperator.IN ||
filter.operator === FilterOperator.NIN
) {
return {
clause: `metadata->>'${filter.key}' ${this.toPostgresOperator(filter.operator)}($${paramIndex})`,
param: filter.value,
};
}
if (
filter.operator === FilterOperator.ALL ||
filter.operator === FilterOperator.ANY
) {
return {
clause: `metadata->'${filter.key}' ${this.toPostgresOperator(filter.operator)} $${paramIndex}::text[]`,
param: filter.value,
};
}
if (filter.operator === FilterOperator.CONTAINS) {
return {
clause: `metadata->'${filter.key}' ${this.toPostgresOperator(filter.operator)} $${paramIndex}::jsonb`,
param: JSON.stringify([filter.value]),
};
}
if (filter.operator === FilterOperator.IS_EMPTY) {
return {
clause: `(NOT (metadata ? '${filter.key}') OR metadata->>'${filter.key}' IS NULL OR metadata->>'${filter.key}' = '' OR metadata->'${filter.key}' = '[]'::jsonb)`,
param: undefined,
};
}
if (filter.operator === FilterOperator.TEXT_MATCH) {
const escapedValue = escapeLikeString(filter.value as string);
return {
clause: `metadata->>'${filter.key}' LIKE $${paramIndex}`,
param: `%${escapedValue}%`,
};
}
// if value is number, coerce metadata value to float
if (typeof filter.value === "number") {
return {
clause: `(metadata->>'${filter.key}')::float ${this.toPostgresOperator(filter.operator)} $${paramIndex}`,
param: filter.value,
};
}
return {
clause: `metadata->>'${filter.key}' ${this.toPostgresOperator(filter.operator)} $${paramIndex}`,
param: filter.value,
};
}
/**
* Query the vector store for the closest matching data to the query embeddings
* @param query The VectorStoreQuery to be used
@@ -265,19 +385,27 @@ export class PGVectorStore
const max = query.similarityTopK ?? 2;
const whereClauses = this.collection.length ? ["collection = $2"] : [];
const params: Array<string | number> = this.collection.length
const params: Array<MetadataFilterValue> = this.collection.length
? [embedding, this.collection]
: [embedding];
const filterClauses: string[] = [];
query.filters?.filters.forEach((filter, index) => {
const paramIndex = params.length + 1;
whereClauses.push(`metadata->>'${filter.key}' = $${paramIndex}`);
// TODO: support filter with other operators
if (!Array.isArray(filter.value) && filter.value) {
params.push(filter.value);
const { clause, param } = this.buildFilterClause(filter, paramIndex);
filterClauses.push(clause);
if (param) {
params.push(param);
}
});
if (filterClauses.length > 0) {
const condition = this.toPostgresCondition(
query.filters?.condition ?? FilterCondition.AND,
);
whereClauses.push(`(${filterClauses.join(` ${condition} `)})`);
}
const where =
whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
@@ -104,3 +104,7 @@ export const parseNumberValue = (value?: MetadataFilterValue): number => {
if (typeof value !== "number") throw new Error("Value must be a number");
return value;
};
export const escapeLikeString = (value: string) => {
return value.replace(/[%_\\]/g, "\\$&");
};