@flowrag/core 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +45 -1
- package/dist/index.mjs +135 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,21 @@ interface Embedder {
|
|
|
10
10
|
embedBatch(texts: string[]): Promise<number[][]>;
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
|
+
//#region src/interfaces/evaluator.d.ts
|
|
14
|
+
/** Document passed to an evaluator */
|
|
15
|
+
interface EvalDocument {
|
|
16
|
+
content: string;
|
|
17
|
+
score: number;
|
|
18
|
+
}
|
|
19
|
+
/** Evaluation result with named scores */
|
|
20
|
+
interface EvalResult {
|
|
21
|
+
scores: Record<string, number>;
|
|
22
|
+
}
|
|
23
|
+
/** Pluggable evaluator for RAG quality metrics */
|
|
24
|
+
interface Evaluator {
|
|
25
|
+
evaluate(query: string, documents: EvalDocument[], reference?: string): Promise<EvalResult>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
13
28
|
//#region src/schema.d.ts
|
|
14
29
|
/** Custom field definition */
|
|
15
30
|
interface FieldDefinition {
|
|
@@ -131,10 +146,17 @@ interface ExtractedRelation {
|
|
|
131
146
|
keywords: string[];
|
|
132
147
|
fields?: Record<string, unknown>;
|
|
133
148
|
}
|
|
149
|
+
/** Token usage from LLM/embedding calls */
|
|
150
|
+
interface TokenUsage {
|
|
151
|
+
promptTokens?: number;
|
|
152
|
+
completionTokens?: number;
|
|
153
|
+
totalTokens?: number;
|
|
154
|
+
}
|
|
134
155
|
/** Result of entity extraction */
|
|
135
156
|
interface ExtractionResult {
|
|
136
157
|
entities: ExtractedEntity[];
|
|
137
158
|
relations: ExtractedRelation[];
|
|
159
|
+
usage?: TokenUsage;
|
|
138
160
|
}
|
|
139
161
|
/** Query modes */
|
|
140
162
|
type QueryMode = "local" | "global" | "hybrid" | "naive";
|
|
@@ -145,6 +167,18 @@ interface LLMExtractor {
|
|
|
145
167
|
extractEntities(content: string, knownEntities: string[], schema: Schema): Promise<ExtractionResult>;
|
|
146
168
|
}
|
|
147
169
|
//#endregion
|
|
170
|
+
//#region src/interfaces/parser.d.ts
|
|
171
|
+
/** Parsed document output from a DocumentParser */
|
|
172
|
+
interface ParsedDocument {
|
|
173
|
+
content: string;
|
|
174
|
+
metadata: Record<string, unknown>;
|
|
175
|
+
}
|
|
176
|
+
/** Pluggable file parser for non-text documents (PDF, DOCX, images, etc.) */
|
|
177
|
+
interface DocumentParser {
|
|
178
|
+
readonly supportedExtensions: string[];
|
|
179
|
+
parse(filePath: string): Promise<ParsedDocument>;
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
148
182
|
//#region src/interfaces/reranker.d.ts
|
|
149
183
|
/**
|
|
150
184
|
* Reranker interface for FlowRAG
|
|
@@ -195,11 +229,21 @@ interface GraphStorage {
|
|
|
195
229
|
deleteRelation(id: Id): Promise<void>;
|
|
196
230
|
}
|
|
197
231
|
//#endregion
|
|
232
|
+
//#region src/namespace.d.ts
|
|
233
|
+
/** Storage set for FlowRAG */
|
|
234
|
+
interface StorageSet {
|
|
235
|
+
kv: KVStorage;
|
|
236
|
+
vector: VectorStorage;
|
|
237
|
+
graph: GraphStorage;
|
|
238
|
+
}
|
|
239
|
+
/** Wrap storage with namespace isolation for multi-tenancy. */
|
|
240
|
+
declare function withNamespace(storage: StorageSet, namespace: string): StorageSet;
|
|
241
|
+
//#endregion
|
|
198
242
|
//#region src/prompt.d.ts
|
|
199
243
|
/**
|
|
200
244
|
* Build the standard entity extraction prompt used by all LLM providers.
|
|
201
245
|
*/
|
|
202
246
|
declare function buildExtractionPrompt(content: string, knownEntities: string[], schema: Schema): string;
|
|
203
247
|
//#endregion
|
|
204
|
-
export { Chunk, Document, DocumentMetadata, Embedder, Entity, EntityFilter, ExtractedEntity, ExtractedRelation, ExtractionResult, FieldDefinition, GraphStorage, Id, KVStorage, LLMExtractor, QueryMode, Relation, RelationDirection, RerankDocument, RerankResult, Reranker, Schema, SchemaConfig, SearchResult, VectorFilter, VectorRecord, VectorStorage, buildExtractionPrompt, defineSchema };
|
|
248
|
+
export { Chunk, Document, DocumentMetadata, DocumentParser, Embedder, Entity, EntityFilter, EvalDocument, EvalResult, Evaluator, ExtractedEntity, ExtractedRelation, ExtractionResult, FieldDefinition, GraphStorage, Id, KVStorage, LLMExtractor, ParsedDocument, QueryMode, Relation, RelationDirection, RerankDocument, RerankResult, Reranker, Schema, SchemaConfig, SearchResult, StorageSet, TokenUsage, VectorFilter, VectorRecord, VectorStorage, buildExtractionPrompt, defineSchema, withNamespace };
|
|
205
249
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,139 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
//#region src/namespace.ts
|
|
4
|
+
function pfx(ns, id) {
|
|
5
|
+
return `${ns}:${id}`;
|
|
6
|
+
}
|
|
7
|
+
function unpfx(ns, id) {
|
|
8
|
+
return id.slice(ns.length + 1);
|
|
9
|
+
}
|
|
10
|
+
var NamespacedKVStorage = class {
|
|
11
|
+
constructor(inner, ns) {
|
|
12
|
+
this.inner = inner;
|
|
13
|
+
this.ns = ns;
|
|
14
|
+
}
|
|
15
|
+
get(key) {
|
|
16
|
+
return this.inner.get(pfx(this.ns, key));
|
|
17
|
+
}
|
|
18
|
+
set(key, value) {
|
|
19
|
+
return this.inner.set(pfx(this.ns, key), value);
|
|
20
|
+
}
|
|
21
|
+
delete(key) {
|
|
22
|
+
return this.inner.delete(pfx(this.ns, key));
|
|
23
|
+
}
|
|
24
|
+
async list(prefix) {
|
|
25
|
+
return (await this.inner.list(pfx(this.ns, prefix ?? ""))).map((k) => unpfx(this.ns, k));
|
|
26
|
+
}
|
|
27
|
+
async clear() {
|
|
28
|
+
const keys = await this.inner.list(`${this.ns}:`);
|
|
29
|
+
await Promise.all(keys.map((k) => this.inner.delete(k)));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var NamespacedVectorStorage = class {
|
|
33
|
+
constructor(inner, ns) {
|
|
34
|
+
this.inner = inner;
|
|
35
|
+
this.ns = ns;
|
|
36
|
+
}
|
|
37
|
+
upsert(records) {
|
|
38
|
+
return this.inner.upsert(records.map((r) => ({
|
|
39
|
+
...r,
|
|
40
|
+
id: pfx(this.ns, r.id),
|
|
41
|
+
metadata: {
|
|
42
|
+
...r.metadata,
|
|
43
|
+
__ns: this.ns
|
|
44
|
+
}
|
|
45
|
+
})));
|
|
46
|
+
}
|
|
47
|
+
async search(vector, limit, filter) {
|
|
48
|
+
return (await this.inner.search(vector, limit, {
|
|
49
|
+
...filter,
|
|
50
|
+
__ns: this.ns
|
|
51
|
+
})).map((r) => ({
|
|
52
|
+
...r,
|
|
53
|
+
id: unpfx(this.ns, r.id),
|
|
54
|
+
metadata: {
|
|
55
|
+
...r.metadata,
|
|
56
|
+
__ns: void 0
|
|
57
|
+
}
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
delete(ids) {
|
|
61
|
+
return this.inner.delete(ids.map((id) => pfx(this.ns, id)));
|
|
62
|
+
}
|
|
63
|
+
count() {
|
|
64
|
+
return this.inner.count();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var NamespacedGraphStorage = class {
|
|
68
|
+
constructor(inner, ns) {
|
|
69
|
+
this.inner = inner;
|
|
70
|
+
this.ns = ns;
|
|
71
|
+
}
|
|
72
|
+
addEntity(entity) {
|
|
73
|
+
return this.inner.addEntity({
|
|
74
|
+
...entity,
|
|
75
|
+
id: pfx(this.ns, entity.id),
|
|
76
|
+
sourceChunkIds: entity.sourceChunkIds.map((id) => pfx(this.ns, id))
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
addRelation(relation) {
|
|
80
|
+
return this.inner.addRelation({
|
|
81
|
+
...relation,
|
|
82
|
+
id: pfx(this.ns, relation.id),
|
|
83
|
+
sourceId: pfx(this.ns, relation.sourceId),
|
|
84
|
+
targetId: pfx(this.ns, relation.targetId),
|
|
85
|
+
sourceChunkIds: relation.sourceChunkIds.map((id) => pfx(this.ns, id))
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async getEntity(id) {
|
|
89
|
+
const e = await this.inner.getEntity(pfx(this.ns, id));
|
|
90
|
+
return e ? this.unpfxEntity(e) : null;
|
|
91
|
+
}
|
|
92
|
+
async getEntities(filter) {
|
|
93
|
+
return (await this.inner.getEntities(filter)).filter((e) => e.id.startsWith(`${this.ns}:`)).map((e) => this.unpfxEntity(e));
|
|
94
|
+
}
|
|
95
|
+
async getRelations(entityId, direction) {
|
|
96
|
+
return (await this.inner.getRelations(pfx(this.ns, entityId), direction)).map((r) => this.unpfxRelation(r));
|
|
97
|
+
}
|
|
98
|
+
async traverse(startId, depth, relationTypes) {
|
|
99
|
+
return (await this.inner.traverse(pfx(this.ns, startId), depth, relationTypes)).map((e) => this.unpfxEntity(e));
|
|
100
|
+
}
|
|
101
|
+
async findPath(fromId, toId, maxDepth) {
|
|
102
|
+
return (await this.inner.findPath(pfx(this.ns, fromId), pfx(this.ns, toId), maxDepth)).map((r) => this.unpfxRelation(r));
|
|
103
|
+
}
|
|
104
|
+
deleteEntity(id) {
|
|
105
|
+
return this.inner.deleteEntity(pfx(this.ns, id));
|
|
106
|
+
}
|
|
107
|
+
deleteRelation(id) {
|
|
108
|
+
return this.inner.deleteRelation(pfx(this.ns, id));
|
|
109
|
+
}
|
|
110
|
+
unpfxEntity(e) {
|
|
111
|
+
return {
|
|
112
|
+
...e,
|
|
113
|
+
id: unpfx(this.ns, e.id),
|
|
114
|
+
sourceChunkIds: e.sourceChunkIds.map((id) => unpfx(this.ns, id))
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
unpfxRelation(r) {
|
|
118
|
+
return {
|
|
119
|
+
...r,
|
|
120
|
+
id: unpfx(this.ns, r.id),
|
|
121
|
+
sourceId: unpfx(this.ns, r.sourceId),
|
|
122
|
+
targetId: unpfx(this.ns, r.targetId),
|
|
123
|
+
sourceChunkIds: r.sourceChunkIds.map((id) => unpfx(this.ns, id))
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
/** Wrap storage with namespace isolation for multi-tenancy. */
|
|
128
|
+
function withNamespace(storage, namespace) {
|
|
129
|
+
return {
|
|
130
|
+
kv: new NamespacedKVStorage(storage.kv, namespace),
|
|
131
|
+
vector: new NamespacedVectorStorage(storage.vector, namespace),
|
|
132
|
+
graph: new NamespacedGraphStorage(storage.graph, namespace)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
//#endregion
|
|
3
137
|
//#region src/prompt.ts
|
|
4
138
|
/**
|
|
5
139
|
* Build the standard entity extraction prompt used by all LLM providers.
|
|
@@ -72,5 +206,5 @@ function defineSchema(config) {
|
|
|
72
206
|
}
|
|
73
207
|
|
|
74
208
|
//#endregion
|
|
75
|
-
export { buildExtractionPrompt, defineSchema };
|
|
209
|
+
export { buildExtractionPrompt, defineSchema, withNamespace };
|
|
76
210
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/prompt.ts","../src/schema.ts"],"sourcesContent":["import type { Schema } from './schema.js';\n\n/**\n * Build the standard entity extraction prompt used by all LLM providers.\n */\nexport function buildExtractionPrompt(\n content: string,\n knownEntities: string[],\n schema: Schema,\n): string {\n const entityTypes = schema.entityTypes.join(', ');\n const relationTypes = schema.relationTypes.join(', ');\n const knownEntitiesList =\n knownEntities.length > 0 ? `\\n\\nKnown entities to reference: ${knownEntities.join(', ')}` : '';\n\n const entityFieldsDef =\n Object.keys(schema.entityFields).length > 0\n ? `\\n\\nEntity custom fields: ${JSON.stringify(schema.entityFields)}`\n : '';\n const relationFieldsDef =\n Object.keys(schema.relationFields).length > 0\n ? `\\n\\nRelation custom fields: ${JSON.stringify(schema.relationFields)}`\n : '';\n\n const fieldsInstruction =\n entityFieldsDef || relationFieldsDef\n ? '\\nInclude a \"fields\" object in each entity/relation with the custom field values when applicable.'\n : '';\n\n return `Extract entities and relations from the following content.\n\nEntity types: ${entityTypes}\nRelation types: ${relationTypes}${knownEntitiesList}${entityFieldsDef}${relationFieldsDef}\n\nContent:\n${content}\n\nReturn a JSON object with this structure:\n{\n \"entities\": [\n {\n \"name\": \"entity name\",\n \"type\": \"entity type from the list above, or 'Other' if not matching\",\n \"description\": \"brief description of the entity\"${entityFieldsDef ? ',\\n \"fields\": {}' : ''}\n }\n ],\n \"relations\": [\n {\n \"source\": \"source entity name\",\n \"target\": \"target entity name\",\n \"type\": \"relation type from the list above\",\n \"description\": \"description of the relationship\",\n \"keywords\": [\"keyword1\", \"keyword2\"]${relationFieldsDef ? ',\\n \"fields\": {}' : ''}\n }\n ]\n}\n\nFocus on technical entities and their relationships. Be precise and avoid duplicates.${fieldsInstruction}`;\n}\n","/**\n * Schema definition for FlowRAG\n */\n\nimport { z } from 'zod';\n\n/** Custom field definition */\nexport interface FieldDefinition {\n type: 'string' | 'enum';\n values?: string[];\n default?: string;\n filterable?: boolean;\n}\n\n/** Schema configuration input */\nexport interface SchemaConfig<\n E extends readonly string[] = readonly string[],\n R extends readonly string[] = readonly string[],\n> {\n entityTypes: E;\n relationTypes: R;\n documentFields?: Record<string, FieldDefinition>;\n entityFields?: Record<string, FieldDefinition>;\n relationFields?: Record<string, FieldDefinition>;\n}\n\n/** Resolved schema with validation */\nexport interface Schema<\n E extends readonly string[] = readonly string[],\n R extends readonly string[] = readonly string[],\n> {\n entityTypes: E;\n relationTypes: R;\n documentFields: Record<string, FieldDefinition>;\n entityFields: Record<string, FieldDefinition>;\n relationFields: Record<string, FieldDefinition>;\n isValidEntityType: (type: string) => boolean;\n isValidRelationType: (type: string) => boolean;\n normalizeEntityType: (type: string) => E[number] | 'Other';\n normalizeRelationType: (type: string) => R[number] | 'Other';\n}\n\nconst schemaConfigSchema = z.object({\n entityTypes: z.array(z.string()).min(1),\n relationTypes: z.array(z.string()).min(1),\n});\n\n/**\n * Define a schema for entity and relation types.\n * Types are suggestions - if LLM extracts a type not in the list, it falls back to 'Other'.\n */\nexport function defineSchema<const E extends readonly string[], const R extends readonly string[]>(\n config: SchemaConfig<E, R>,\n): Schema<E, R> {\n schemaConfigSchema.parse(config);\n\n const entitySet = new Set<string>(config.entityTypes);\n const relationSet = new Set<string>(config.relationTypes);\n\n return {\n entityTypes: config.entityTypes,\n relationTypes: config.relationTypes,\n documentFields: config.documentFields ?? {},\n entityFields: config.entityFields ?? {},\n relationFields: config.relationFields ?? {},\n isValidEntityType: (type: string) => entitySet.has(type),\n isValidRelationType: (type: string) => relationSet.has(type),\n normalizeEntityType: (type: string) => (entitySet.has(type) ? (type as E[number]) : 'Other'),\n normalizeRelationType: (type: string) =>\n relationSet.has(type) ? (type as R[number]) : 'Other',\n };\n}\n"],"mappings":";;;;;;AAKA,SAAgB,sBACd,SACA,eACA,QACQ;CACR,MAAM,cAAc,OAAO,YAAY,KAAK,KAAK;CACjD,MAAM,gBAAgB,OAAO,cAAc,KAAK,KAAK;CACrD,MAAM,oBACJ,cAAc,SAAS,IAAI,oCAAoC,cAAc,KAAK,KAAK,KAAK;CAE9F,MAAM,kBACJ,OAAO,KAAK,OAAO,aAAa,CAAC,SAAS,IACtC,6BAA6B,KAAK,UAAU,OAAO,aAAa,KAChE;CACN,MAAM,oBACJ,OAAO,KAAK,OAAO,eAAe,CAAC,SAAS,IACxC,+BAA+B,KAAK,UAAU,OAAO,eAAe,KACpE;AAON,QAAO;;gBAEO,YAAY;kBACV,gBAAgB,oBAAoB,kBAAkB,kBAAkB;;;EAGxF,QAAQ;;;;;;;;wDAQ8C,kBAAkB,4BAA0B,GAAG;;;;;;;;;4CAS3D,oBAAoB,4BAA0B,GAAG;;;;;uFA3BzF,mBAAmB,oBACf,wGACA;;;;;;;;ACeR,MAAM,qBAAqB,EAAE,OAAO;CAClC,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE;CACvC,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE;CAC1C,CAAC;;;;;AAMF,SAAgB,aACd,QACc;AACd,oBAAmB,MAAM,OAAO;CAEhC,MAAM,YAAY,IAAI,IAAY,OAAO,YAAY;CACrD,MAAM,cAAc,IAAI,IAAY,OAAO,cAAc;AAEzD,QAAO;EACL,aAAa,OAAO;EACpB,eAAe,OAAO;EACtB,gBAAgB,OAAO,kBAAkB,EAAE;EAC3C,cAAc,OAAO,gBAAgB,EAAE;EACvC,gBAAgB,OAAO,kBAAkB,EAAE;EAC3C,oBAAoB,SAAiB,UAAU,IAAI,KAAK;EACxD,sBAAsB,SAAiB,YAAY,IAAI,KAAK;EAC5D,sBAAsB,SAAkB,UAAU,IAAI,KAAK,GAAI,OAAqB;EACpF,wBAAwB,SACtB,YAAY,IAAI,KAAK,GAAI,OAAqB;EACjD"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/namespace.ts","../src/prompt.ts","../src/schema.ts"],"sourcesContent":["/**\n * Multi-tenancy namespace wrappers for storage isolation.\n */\n\nimport type { GraphStorage, KVStorage, VectorStorage } from './interfaces/storage.js';\nimport type {\n Entity,\n EntityFilter,\n Id,\n Relation,\n RelationDirection,\n SearchResult,\n VectorFilter,\n VectorRecord,\n} from './types.js';\n\nfunction pfx(ns: string, id: string): string {\n return `${ns}:${id}`;\n}\n\nfunction unpfx(ns: string, id: string): string {\n return id.slice(ns.length + 1);\n}\n\nclass NamespacedKVStorage implements KVStorage {\n constructor(\n private inner: KVStorage,\n private ns: string,\n ) {}\n\n get<T>(key: string): Promise<T | null> {\n return this.inner.get<T>(pfx(this.ns, key));\n }\n\n set<T>(key: string, value: T): Promise<void> {\n return this.inner.set(pfx(this.ns, key), value);\n }\n\n delete(key: string): Promise<void> {\n return this.inner.delete(pfx(this.ns, key));\n }\n\n async list(prefix?: string): Promise<string[]> {\n const keys = await this.inner.list(pfx(this.ns, prefix ?? ''));\n return keys.map((k) => unpfx(this.ns, k));\n }\n\n async clear(): Promise<void> {\n const keys = await this.inner.list(`${this.ns}:`);\n await Promise.all(keys.map((k) => this.inner.delete(k)));\n }\n}\n\nclass NamespacedVectorStorage implements VectorStorage {\n constructor(\n private inner: VectorStorage,\n private ns: string,\n ) {}\n\n upsert(records: VectorRecord[]): Promise<void> {\n return this.inner.upsert(\n records.map((r) => ({\n ...r,\n id: pfx(this.ns, r.id),\n metadata: { ...r.metadata, __ns: this.ns },\n })),\n );\n }\n\n async search(vector: number[], limit: number, filter?: VectorFilter): Promise<SearchResult[]> {\n const results = await this.inner.search(vector, limit, { ...filter, __ns: this.ns });\n return results.map((r) => ({\n ...r,\n id: unpfx(this.ns, r.id),\n metadata: { ...r.metadata, __ns: undefined },\n }));\n }\n\n delete(ids: Id[]): Promise<void> {\n return this.inner.delete(ids.map((id) => pfx(this.ns, id)));\n }\n\n count(): Promise<number> {\n return this.inner.count();\n }\n}\n\nclass NamespacedGraphStorage implements GraphStorage {\n constructor(\n private inner: GraphStorage,\n private ns: string,\n ) {}\n\n addEntity(entity: Entity): Promise<void> {\n return this.inner.addEntity({\n ...entity,\n id: pfx(this.ns, entity.id),\n sourceChunkIds: entity.sourceChunkIds.map((id) => pfx(this.ns, id)),\n });\n }\n\n addRelation(relation: Relation): Promise<void> {\n return this.inner.addRelation({\n ...relation,\n id: pfx(this.ns, relation.id),\n sourceId: pfx(this.ns, relation.sourceId),\n targetId: pfx(this.ns, relation.targetId),\n sourceChunkIds: relation.sourceChunkIds.map((id) => pfx(this.ns, id)),\n });\n }\n\n async getEntity(id: Id): Promise<Entity | null> {\n const e = await this.inner.getEntity(pfx(this.ns, id));\n return e ? this.unpfxEntity(e) : null;\n }\n\n async getEntities(filter?: EntityFilter): Promise<Entity[]> {\n const all = await this.inner.getEntities(filter);\n return all.filter((e) => e.id.startsWith(`${this.ns}:`)).map((e) => this.unpfxEntity(e));\n }\n\n async getRelations(entityId: Id, direction?: RelationDirection): Promise<Relation[]> {\n const rels = await this.inner.getRelations(pfx(this.ns, entityId), direction);\n return rels.map((r) => this.unpfxRelation(r));\n }\n\n async traverse(startId: Id, depth: number, relationTypes?: string[]): Promise<Entity[]> {\n const entities = await this.inner.traverse(pfx(this.ns, startId), depth, relationTypes);\n return entities.map((e) => this.unpfxEntity(e));\n }\n\n async findPath(fromId: Id, toId: Id, maxDepth?: number): Promise<Relation[]> {\n const rels = await this.inner.findPath(pfx(this.ns, fromId), pfx(this.ns, toId), maxDepth);\n return rels.map((r) => this.unpfxRelation(r));\n }\n\n deleteEntity(id: Id): Promise<void> {\n return this.inner.deleteEntity(pfx(this.ns, id));\n }\n\n deleteRelation(id: Id): Promise<void> {\n return this.inner.deleteRelation(pfx(this.ns, id));\n }\n\n private unpfxEntity(e: Entity): Entity {\n return {\n ...e,\n id: unpfx(this.ns, e.id),\n sourceChunkIds: e.sourceChunkIds.map((id) => unpfx(this.ns, id)),\n };\n }\n\n private unpfxRelation(r: Relation): Relation {\n return {\n ...r,\n id: unpfx(this.ns, r.id),\n sourceId: unpfx(this.ns, r.sourceId),\n targetId: unpfx(this.ns, r.targetId),\n sourceChunkIds: r.sourceChunkIds.map((id) => unpfx(this.ns, id)),\n };\n }\n}\n\n/** Storage set for FlowRAG */\nexport interface StorageSet {\n kv: KVStorage;\n vector: VectorStorage;\n graph: GraphStorage;\n}\n\n/** Wrap storage with namespace isolation for multi-tenancy. */\nexport function withNamespace(storage: StorageSet, namespace: string): StorageSet {\n return {\n kv: new NamespacedKVStorage(storage.kv, namespace),\n vector: new NamespacedVectorStorage(storage.vector, namespace),\n graph: new NamespacedGraphStorage(storage.graph, namespace),\n };\n}\n","import type { Schema } from './schema.js';\n\n/**\n * Build the standard entity extraction prompt used by all LLM providers.\n */\nexport function buildExtractionPrompt(\n content: string,\n knownEntities: string[],\n schema: Schema,\n): string {\n const entityTypes = schema.entityTypes.join(', ');\n const relationTypes = schema.relationTypes.join(', ');\n const knownEntitiesList =\n knownEntities.length > 0 ? `\\n\\nKnown entities to reference: ${knownEntities.join(', ')}` : '';\n\n const entityFieldsDef =\n Object.keys(schema.entityFields).length > 0\n ? `\\n\\nEntity custom fields: ${JSON.stringify(schema.entityFields)}`\n : '';\n const relationFieldsDef =\n Object.keys(schema.relationFields).length > 0\n ? `\\n\\nRelation custom fields: ${JSON.stringify(schema.relationFields)}`\n : '';\n\n const fieldsInstruction =\n entityFieldsDef || relationFieldsDef\n ? '\\nInclude a \"fields\" object in each entity/relation with the custom field values when applicable.'\n : '';\n\n return `Extract entities and relations from the following content.\n\nEntity types: ${entityTypes}\nRelation types: ${relationTypes}${knownEntitiesList}${entityFieldsDef}${relationFieldsDef}\n\nContent:\n${content}\n\nReturn a JSON object with this structure:\n{\n \"entities\": [\n {\n \"name\": \"entity name\",\n \"type\": \"entity type from the list above, or 'Other' if not matching\",\n \"description\": \"brief description of the entity\"${entityFieldsDef ? ',\\n \"fields\": {}' : ''}\n }\n ],\n \"relations\": [\n {\n \"source\": \"source entity name\",\n \"target\": \"target entity name\",\n \"type\": \"relation type from the list above\",\n \"description\": \"description of the relationship\",\n \"keywords\": [\"keyword1\", \"keyword2\"]${relationFieldsDef ? ',\\n \"fields\": {}' : ''}\n }\n ]\n}\n\nFocus on technical entities and their relationships. Be precise and avoid duplicates.${fieldsInstruction}`;\n}\n","/**\n * Schema definition for FlowRAG\n */\n\nimport { z } from 'zod';\n\n/** Custom field definition */\nexport interface FieldDefinition {\n type: 'string' | 'enum';\n values?: string[];\n default?: string;\n filterable?: boolean;\n}\n\n/** Schema configuration input */\nexport interface SchemaConfig<\n E extends readonly string[] = readonly string[],\n R extends readonly string[] = readonly string[],\n> {\n entityTypes: E;\n relationTypes: R;\n documentFields?: Record<string, FieldDefinition>;\n entityFields?: Record<string, FieldDefinition>;\n relationFields?: Record<string, FieldDefinition>;\n}\n\n/** Resolved schema with validation */\nexport interface Schema<\n E extends readonly string[] = readonly string[],\n R extends readonly string[] = readonly string[],\n> {\n entityTypes: E;\n relationTypes: R;\n documentFields: Record<string, FieldDefinition>;\n entityFields: Record<string, FieldDefinition>;\n relationFields: Record<string, FieldDefinition>;\n isValidEntityType: (type: string) => boolean;\n isValidRelationType: (type: string) => boolean;\n normalizeEntityType: (type: string) => E[number] | 'Other';\n normalizeRelationType: (type: string) => R[number] | 'Other';\n}\n\nconst schemaConfigSchema = z.object({\n entityTypes: z.array(z.string()).min(1),\n relationTypes: z.array(z.string()).min(1),\n});\n\n/**\n * Define a schema for entity and relation types.\n * Types are suggestions - if LLM extracts a type not in the list, it falls back to 'Other'.\n */\nexport function defineSchema<const E extends readonly string[], const R extends readonly string[]>(\n config: SchemaConfig<E, R>,\n): Schema<E, R> {\n schemaConfigSchema.parse(config);\n\n const entitySet = new Set<string>(config.entityTypes);\n const relationSet = new Set<string>(config.relationTypes);\n\n return {\n entityTypes: config.entityTypes,\n relationTypes: config.relationTypes,\n documentFields: config.documentFields ?? {},\n entityFields: config.entityFields ?? {},\n relationFields: config.relationFields ?? {},\n isValidEntityType: (type: string) => entitySet.has(type),\n isValidRelationType: (type: string) => relationSet.has(type),\n normalizeEntityType: (type: string) => (entitySet.has(type) ? (type as E[number]) : 'Other'),\n normalizeRelationType: (type: string) =>\n relationSet.has(type) ? (type as R[number]) : 'Other',\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowrag/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "📐 The heart of FlowRAG. Defines all TypeScript interfaces (Storage, Embedder, LLMExtractor), the Zod-based schema system for defining entity/relation types, and the orchestration pipeline that coordinates indexing and querying. This package contains only contracts and types, no concrete implementations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"interfaces",
|