From 9aad38eb8721f2a0793fb0839ce609dd25f1fba9 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 24 Dec 2024 16:50:30 +0200 Subject: [PATCH] resolve conflicts and update missing files --- .../src/{ => chains}/graph_db_falkordb.ts | 6 +- libs/langchain-community/langchain.config.js | 4 +- libs/langchain-community/package.json | 19 ++++ .../graphs/{falkordb_graph.ts => falkordb.ts} | 90 +++++++++---------- .../graphs/tests/falkordb_graph.int.test.ts | 19 +++- .../src/load/import_constants.ts | 2 +- 6 files changed, 88 insertions(+), 52 deletions(-) rename examples/src/{ => chains}/graph_db_falkordb.ts (90%) rename libs/langchain-community/src/graphs/{falkordb_graph.ts => falkordb.ts} (59%) diff --git a/examples/src/graph_db_falkordb.ts b/examples/src/chains/graph_db_falkordb.ts similarity index 90% rename from examples/src/graph_db_falkordb.ts rename to examples/src/chains/graph_db_falkordb.ts index b4cf9826aafb..3f943e404ab8 100644 --- a/examples/src/graph_db_falkordb.ts +++ b/examples/src/chains/graph_db_falkordb.ts @@ -1,5 +1,5 @@ -import { FalkorDBGraph } from "@langchain/community/graphs/falkordb_graph"; -import { OpenAI } from "@langchain/llms/openai"; +import { FalkorDBGraph } from "@langchain/community/graphs/falkordb"; +import { OpenAI } from "@langchain/openai"; import { GraphCypherQAChain } from "langchain/chains/graph_qa/cypher"; /** @@ -18,6 +18,8 @@ await graph.query( "-[:ACTED_IN]->(:Movie {title: 'Pulp Fiction'})" ); +await graph.refreshSchema(); + const chain = GraphCypherQAChain.fromLLM({ llm: model, graph, diff --git a/libs/langchain-community/langchain.config.js b/libs/langchain-community/langchain.config.js index 40dbe23bdc9c..65fd42630323 100644 --- a/libs/langchain-community/langchain.config.js +++ b/libs/langchain-community/langchain.config.js @@ -223,7 +223,7 @@ export const config = { // graphs "graphs/neo4j_graph": "graphs/neo4j_graph", "graphs/memgraph_graph": "graphs/memgraph_graph", - "graphs/memgraph_graph": "graphs/falkordb_graph", + "graphs/falkordb": "graphs/falkordb", // document_compressors "document_compressors/ibm": "document_compressors/ibm", // document transformers @@ -454,7 +454,7 @@ export const config = { "cache/upstash_redis", "graphs/neo4j_graph", "graphs/memgraph_graph", - "graphs/falkordb_graph", + "graphs/falkordb", // document_compressors "document_compressors/ibm", // document_transformers diff --git a/libs/langchain-community/package.json b/libs/langchain-community/package.json index b759b36153af..7cb46b071065 100644 --- a/libs/langchain-community/package.json +++ b/libs/langchain-community/package.json @@ -38,6 +38,7 @@ "@langchain/openai": ">=0.2.0 <0.4.0", "binary-extensions": "^2.2.0", "expr-eval": "^2.0.2", + "falkordb": "^6.2.5", "flat": "^5.0.2", "js-yaml": "^4.1.0", "langchain": ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0", @@ -189,6 +190,7 @@ "mongodb": "^5.2.0", "mysql2": "^3.9.8", "neo4j-driver": "^5.17.0", + "falkordb": "^6.2.5", "node-llama-cpp": "3.1.1", "notion-to-md": "^3.1.0", "officeparser": "^4.0.4", @@ -321,6 +323,7 @@ "mongodb": ">=5.2.0", "mysql2": "^3.9.8", "neo4j-driver": "*", + "falkordb": "*", "notion-to-md": "^3.1.0", "officeparser": "^4.0.4", "openai": "*", @@ -638,6 +641,9 @@ "neo4j-driver": { "optional": true }, + "falkordb": { + "optional": true + }, "notion-to-md": { "optional": true }, @@ -2323,6 +2329,15 @@ "import": "./graphs/memgraph_graph.js", "require": "./graphs/memgraph_graph.cjs" }, + "./graphs/falkordb": { + "types": { + "import": "./graphs/falkordb.d.ts", + "require": "./graphs/falkordb.d.cts", + "default": "./graphs/falkordb.d.ts" + }, + "import": "./graphs/falkordb.js", + "require": "./graphs/falkordb.cjs" + }, "./document_compressors/ibm": { "types": { "import": "./document_compressors/ibm.d.ts", @@ -3862,6 +3877,10 @@ "graphs/memgraph_graph.js", "graphs/memgraph_graph.d.ts", "graphs/memgraph_graph.d.cts", + "graphs/falkordb.cjs", + "graphs/falkordb.js", + "graphs/falkordb.d.ts", + "graphs/falkordb.d.cts", "document_compressors/ibm.cjs", "document_compressors/ibm.js", "document_compressors/ibm.d.ts", diff --git a/libs/langchain-community/src/graphs/falkordb_graph.ts b/libs/langchain-community/src/graphs/falkordb.ts similarity index 59% rename from libs/langchain-community/src/graphs/falkordb_graph.ts rename to libs/langchain-community/src/graphs/falkordb.ts index 9e3900eecf64..5a1963cc08eb 100644 --- a/libs/langchain-community/src/graphs/falkordb_graph.ts +++ b/libs/langchain-community/src/graphs/falkordb.ts @@ -1,6 +1,4 @@ -import { createClient } from "redis"; -import { Graph } from "redisgraph.js"; - +import { FalkorDB, Graph } from "falkordb"; // eslint-disable-next-line @typescript-eslint/no-explicit-any interface FalkorDBGraphConfig { @@ -16,7 +14,7 @@ interface StructuredSchema { } export class FalkorDBGraph { - private driver; + private driver: FalkorDB; private graph: Graph; private schema = ""; private structuredSchema: StructuredSchema = { @@ -26,24 +24,29 @@ export class FalkorDBGraph { }; private enhancedSchema: boolean; - constructor({ url, graph = "falkordb", enhancedSchema = false }: FalkorDBGraphConfig) { + constructor({ enhancedSchema = false }: FalkorDBGraphConfig) { try { - this.driver = createClient({ url }); - this.graph = new Graph(graph); // Initialize the Graph instance this.enhancedSchema = enhancedSchema; } catch (error) { - throw new Error( - "Could not create a FalkorDB driver instance. Please check the connection details." - ); + console.error("Error in FalkorDBGraph constructor:", error); + throw new Error("Failed to initialize FalkorDBGraph."); } } static async initialize(config: FalkorDBGraphConfig): Promise { const graph = new FalkorDBGraph(config); + const driver = await FalkorDB.connect({ + socket: { + host: new URL(config.url).hostname, + port: parseInt(new URL(config.url).port), + }, + }); + graph.driver = driver; await graph.verifyConnectivity(); - await graph.refreshSchema(); + return graph; } + getSchema(): string { return this.schema; @@ -53,25 +56,18 @@ export class FalkorDBGraph { return this.structuredSchema; } - async query(query: string): Promise { - const resultSet = await this.graph.query(query); // Run the query - const rows = []; - - // Iterate through the ResultSet - while (resultSet.hasNext()) { - const record = resultSet.next(); // Get the next record - const keys = record.keys(); // Get column names - const values = record.values(); // Get values - const obj = Object.fromEntries(keys.map((key, i) => [key, values[i]])); // Map keys to values - rows.push(obj); // Add the object to rows - } - - return rows; + async selectGraph(graphName: string): Promise { + this.graph = await this.driver.selectGraph(graphName); + } + + async query(query: string): Promise { + return await this.graph.query(query); } async verifyConnectivity(): Promise { - await this.driver.connect(); // Ensure the Redis client is connected + await this.driver.info() } + async refreshSchema(): Promise { const nodePropertiesQuery = ` @@ -98,27 +94,31 @@ export class FalkorDBGraph { RETURN DISTINCT {start: src_label, type: type(r), end: dst_label} AS output `; - const nodeProperties = await this.query(nodePropertiesQuery); - const relationshipsProperties = await this.query(relPropertiesQuery); - const relationships = await this.query(relQuery); - - this.structuredSchema = { - nodeProps: Object.fromEntries( - nodeProperties.map((el: { output: { label: string; properties: string[] } }) => [el.output.label, el.output.properties]) - ), - relProps: Object.fromEntries( - relationshipsProperties.map((el: { output: { type: string; properties: string[] } }) => [el.output.type, el.output.properties]) - ), - relationships: relationships.map((el: { output: { start: string; type: string; end: string } }) => el.output), - }; - - if (this.enhancedSchema) { - this.enhanceSchemaDetails(); - } + const nodePropertiesResult = await this.query(nodePropertiesQuery); + const relationshipsPropertiesResult = await this.query(relPropertiesQuery); + const relationshipsResult = await this.query(relQuery); + + const nodeProperties = nodePropertiesResult.data || []; + const relationshipsProperties = relationshipsPropertiesResult.data || []; + const relationships = relationshipsResult.data || []; + + this.structuredSchema = { + nodeProps: Object.fromEntries( + nodeProperties.map((el: { output: { label: string; properties: string[] } }) => [el.output.label, el.output.properties]) + ), + relProps: Object.fromEntries( + relationshipsProperties.map((el: { output: { type: string; properties: string[] } }) => [el.output.type, el.output.properties]) + ), + relationships: relationships.map((el: { output: { start: string; type: string; end: string } }) => el.output), + }; - this.schema = this.formatSchema(); + if (this.enhancedSchema) { + await this.enhanceSchemaDetails(); } + this.schema = this.formatSchema(); +} + private async enhanceSchemaDetails(): Promise { console.log("Enhanced schema details not yet implemented for FalkorDB."); } @@ -149,6 +149,6 @@ export class FalkorDBGraph { } async close(): Promise { - await this.driver.quit(); + await this.driver.close(); } } \ No newline at end of file diff --git a/libs/langchain-community/src/graphs/tests/falkordb_graph.int.test.ts b/libs/langchain-community/src/graphs/tests/falkordb_graph.int.test.ts index a6103b757950..290eb9025794 100644 --- a/libs/langchain-community/src/graphs/tests/falkordb_graph.int.test.ts +++ b/libs/langchain-community/src/graphs/tests/falkordb_graph.int.test.ts @@ -1,7 +1,7 @@ /* eslint-disable no-process-env */ import { test } from "@jest/globals"; -import { FalkorDBGraph } from "../falkordb_graph.js"; +import { FalkorDBGraph } from "../falkordb.js"; describe("FalkorDB Graph Tests", () => { const url = process.env.FALKORDB_URI as string; @@ -9,6 +9,8 @@ describe("FalkorDB Graph Tests", () => { beforeEach(async () => { graph = await FalkorDBGraph.initialize({ url }); + await graph.selectGraph("falkordbGraph"); + await graph.refreshSchema(); await graph.query("MATCH (n) DETACH DELETE n"); }); @@ -22,7 +24,20 @@ describe("FalkorDB Graph Tests", () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any return graph.query('RETURN "test" AS output').then((output: any) => { const expectedOutput = [{ output: "test" }]; - expect(output).toEqual(expectedOutput); + expect(output.data).toEqual(expectedOutput); }); }); + + test("Verify refreshSchema accurately updates the schema", async () => { + await graph.query(` + CREATE (:Person {name: 'Alice', age: 30})-[:FRIENDS_WITH]->(:Person {name: 'Bob', age: 25}) + `); + await graph.refreshSchema(); + + const schema = graph.getSchema(); + expect(schema).toContain("Person"); + expect(schema).toContain("FRIENDS_WITH"); + expect(schema).toContain("name"); + expect(schema).toContain("age"); + }); }); \ No newline at end of file diff --git a/libs/langchain-community/src/load/import_constants.ts b/libs/langchain-community/src/load/import_constants.ts index eb5de253b404..57ed09fdaf82 100644 --- a/libs/langchain-community/src/load/import_constants.ts +++ b/libs/langchain-community/src/load/import_constants.ts @@ -112,7 +112,7 @@ export const optionalImportEntrypoints: string[] = [ "langchain_community/retrievers/zep_cloud", "langchain_community/graphs/neo4j_graph", "langchain_community/graphs/memgraph_graph", - "langchain_community/graphs/falkordb_graph", + "langchain_community/graphs/falkordb", "langchain_community/document_compressors/ibm", "langchain_community/document_transformers/html_to_text", "langchain_community/document_transformers/mozilla_readability",