From e0f6cc3be1e9a37d4b3f3ae6533f31c1f94fa09b Mon Sep 17 00:00:00 2001 From: Gunnar Holwerda Date: Mon, 9 Dec 2024 11:00:12 -0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20return=20actual=20source=20nodes=20w?= =?UTF-8?q?ith=20compact=20and=20refine=20response=20synt=E2=80=A6=20(#155?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/new-cups-dress.md | 5 ++ .../core/src/response-synthesizers/factory.ts | 31 ++++++++- .../compact-and-refine.test.ts | 66 +++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .changeset/new-cups-dress.md create mode 100644 packages/core/tests/response-synthesizers/compact-and-refine.test.ts diff --git a/.changeset/new-cups-dress.md b/.changeset/new-cups-dress.md new file mode 100644 index 0000000000..ad95ba94dc --- /dev/null +++ b/.changeset/new-cups-dress.md @@ -0,0 +1,5 @@ +--- +"@llamaindex/core": patch +--- + +The compact and refine response synthesizer (retrieved by using `getResponseSynthesizer('compact')`) has been fixed to return the original source nodes that were provided to it in its response. Previous to this it was returning the compacted text chunk documents. diff --git a/packages/core/src/response-synthesizers/factory.ts b/packages/core/src/response-synthesizers/factory.ts index 9197150007..b513c23480 100644 --- a/packages/core/src/response-synthesizers/factory.ts +++ b/packages/core/src/response-synthesizers/factory.ts @@ -77,6 +77,16 @@ class Refine extends BaseSynthesizer { } } + async getResponse( + query: MessageContent, + nodes: NodeWithScore[], + stream: true, + ): Promise>; + async getResponse( + query: MessageContent, + nodes: NodeWithScore[], + stream: false, + ): Promise; async getResponse( query: MessageContent, nodes: NodeWithScore[], @@ -197,6 +207,16 @@ class Refine extends BaseSynthesizer { * CompactAndRefine is a slight variation of Refine that first compacts the text chunks into the smallest possible number of chunks. */ class CompactAndRefine extends Refine { + async getResponse( + query: MessageContent, + nodes: NodeWithScore[], + stream: true, + ): Promise>; + async getResponse( + query: MessageContent, + nodes: NodeWithScore[], + stream: false, + ): Promise; async getResponse( query: MessageContent, nodes: NodeWithScore[], @@ -216,17 +236,24 @@ class CompactAndRefine extends Refine { const newTexts = this.promptHelper.repack(maxPrompt, textChunks); const newNodes = newTexts.map((text) => new TextNode({ text })); if (stream) { - return super.getResponse( + const streamResponse = await super.getResponse( query, newNodes.map((node) => ({ node })), true, ); + return streamConverter(streamResponse, (chunk) => { + chunk.sourceNodes = nodes; + return chunk; + }); } - return super.getResponse( + + const originalResponse = await super.getResponse( query, newNodes.map((node) => ({ node })), false, ); + originalResponse.sourceNodes = nodes; + return originalResponse; } } diff --git a/packages/core/tests/response-synthesizers/compact-and-refine.test.ts b/packages/core/tests/response-synthesizers/compact-and-refine.test.ts new file mode 100644 index 0000000000..fa3cad252e --- /dev/null +++ b/packages/core/tests/response-synthesizers/compact-and-refine.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, test, vi } from "vitest"; +import type { LLMMetadata } from "../../llms/dist/index.js"; +import { getResponseSynthesizer } from "../../response-synthesizers/dist/index.js"; +import { Document } from "../../schema/dist/index.js"; + +const mockLllm = () => ({ + complete: vi.fn().mockImplementation(({ stream }) => { + const response = { text: "unimportant" }; + if (!stream) { + return response; + } + + function* gen() { + // yield a few times to make sure each chunk has the sourceNodes + yield response; + yield response; + yield response; + } + + return gen(); + }), + chat: vi.fn(), + metadata: {} as unknown as LLMMetadata, +}); + +describe("compact and refine response synthesizer", () => { + describe("synthesize", () => { + test("should return original sourceNodes with response when stream = false", async () => { + const synthesizer = getResponseSynthesizer("compact", { + llm: mockLllm(), + }); + + const sourceNode = { node: new Document({}), score: 1 }; + + const response = await synthesizer.synthesize( + { + query: "test", + nodes: [sourceNode], + }, + false, + ); + + expect(response.sourceNodes).toEqual([sourceNode]); + }); + + test("should return original sourceNodes with response when stream = true", async () => { + const synthesizer = getResponseSynthesizer("compact", { + llm: mockLllm(), + }); + + const sourceNode = { node: new Document({}), score: 1 }; + + const response = await synthesizer.synthesize( + { + query: "test", + nodes: [sourceNode], + }, + true, + ); + + for await (const chunk of response) { + expect(chunk.sourceNodes).toEqual([sourceNode]); + } + }); + }); +}); From a0e6f57d9bd085165706168f35a40b3a9b7a5219 Mon Sep 17 00:00:00 2001 From: Gunnar Holwerda Date: Mon, 9 Dec 2024 19:51:52 -0800 Subject: [PATCH 2/3] Pass options through to userWebpack in withLlamaIndex (#1550) --- .changeset/weak-cats-smash.md | 5 +++++ packages/llamaindex/src/next.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/weak-cats-smash.md diff --git a/.changeset/weak-cats-smash.md b/.changeset/weak-cats-smash.md new file mode 100644 index 0000000000..62246011d7 --- /dev/null +++ b/.changeset/weak-cats-smash.md @@ -0,0 +1,5 @@ +--- +"llamaindex": patch +--- + +withLlamaIndex now passes through webpack options to the passed in customized NextJS webpack config. Before it was only passing through the config. diff --git a/packages/llamaindex/src/next.ts b/packages/llamaindex/src/next.ts index e27b524580..fb8f44527a 100644 --- a/packages/llamaindex/src/next.ts +++ b/packages/llamaindex/src/next.ts @@ -41,7 +41,7 @@ export default function withLlamaIndex(config: any) { // eslint-disable-next-line @typescript-eslint/no-explicit-any config.webpack = function (webpackConfig: any, options: any) { if (userWebpack) { - webpackConfig = userWebpack(webpackConfig); + webpackConfig = userWebpack(webpackConfig, options); } webpackConfig.resolve.alias = { ...webpackConfig.resolve.alias, From d99d59849154e112197c34247d0e52bc47be6cd6 Mon Sep 17 00:00:00 2001 From: Qwertic Date: Tue, 10 Dec 2024 04:52:15 +0100 Subject: [PATCH 3/3] Update typescript.mdx (#1557) --- apps/next/src/content/docs/llamaindex/setup/typescript.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/next/src/content/docs/llamaindex/setup/typescript.mdx b/apps/next/src/content/docs/llamaindex/setup/typescript.mdx index 434ab28fd6..b25e5ee542 100644 --- a/apps/next/src/content/docs/llamaindex/setup/typescript.mdx +++ b/apps/next/src/content/docs/llamaindex/setup/typescript.mdx @@ -84,7 +84,7 @@ Imaging you put output file into `/dist/openai.js` but you are importing `llamai } ``` -In old module resolution, TypeScript will not be able to find the module because it is not follow the file structure, even you run `node index.js` successfully. (on Node.js >=16) +In old module resolution, TypeScript will not be able to find the module because it is not following the file structure, even you run `node index.js` successfully. (on Node.js >=16) See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) or [TypeScript 5.0 blog](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler7).