fix(sdk): removing deprecating param from our sdk and docs changes with it (#4740)
This commit is contained in:
@@ -131,7 +131,7 @@ export class ConfigManager {
|
||||
userConfig.historyDbPath ||
|
||||
userConfig.historyStore?.config?.historyDbPath ||
|
||||
DEFAULT_MEMORY_CONFIG.historyStore?.config?.historyDbPath,
|
||||
customPrompt: userConfig.customPrompt,
|
||||
customInstructions: userConfig.customInstructions,
|
||||
graphStore: {
|
||||
...DEFAULT_MEMORY_CONFIG.graphStore,
|
||||
...userConfig.graphStore,
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface GraphStoreConfig {
|
||||
provider: string;
|
||||
config: Neo4jConfig;
|
||||
llm?: LLMConfig;
|
||||
customPrompt?: string;
|
||||
customInstructions?: string;
|
||||
}
|
||||
|
||||
export function validateNeo4jConfig(config: Neo4jConfig): void {
|
||||
|
||||
@@ -136,7 +136,7 @@ export class MemoryGraph {
|
||||
};
|
||||
}
|
||||
|
||||
async search(query: string, filters: Record<string, any>, limit = 100) {
|
||||
async search(query: string, filters: Record<string, any>, topK = 100) {
|
||||
const entityTypeMap = await this._retrieveNodesFromData(query, filters);
|
||||
const searchOutput = await this._searchGraphDb(
|
||||
Object.keys(entityTypeMap),
|
||||
@@ -178,7 +178,7 @@ export class MemoryGraph {
|
||||
}
|
||||
}
|
||||
|
||||
async getAll(filters: Record<string, any>, limit = 100) {
|
||||
async getAll(filters: Record<string, any>, topK = 100) {
|
||||
const session = this.graph.session();
|
||||
try {
|
||||
const result = await session.run(
|
||||
@@ -187,7 +187,7 @@ export class MemoryGraph {
|
||||
RETURN n.name AS source, type(r) AS relationship, m.name AS target
|
||||
LIMIT toInteger($limit)
|
||||
`,
|
||||
{ user_id: filters["userId"], limit: Math.floor(Number(limit)) },
|
||||
{ user_id: filters["userId"], limit: Math.floor(Number(topK)) },
|
||||
);
|
||||
|
||||
const finalResults = result.records.map((record) => ({
|
||||
@@ -253,7 +253,7 @@ export class MemoryGraph {
|
||||
entityTypeMap: Record<string, string>,
|
||||
) {
|
||||
let messages;
|
||||
if (this.config.graphStore?.customPrompt) {
|
||||
if (this.config.graphStore?.customInstructions) {
|
||||
messages = [
|
||||
{
|
||||
role: "system",
|
||||
@@ -263,7 +263,7 @@ export class MemoryGraph {
|
||||
filters["userId"],
|
||||
).replace(
|
||||
"CUSTOM_PROMPT",
|
||||
`4. ${this.config.graphStore.customPrompt}`,
|
||||
`4. ${this.config.graphStore.customInstructions}`,
|
||||
) + "\nPlease provide your response in JSON format.",
|
||||
},
|
||||
{ role: "user", content: data },
|
||||
@@ -307,7 +307,7 @@ export class MemoryGraph {
|
||||
private async _searchGraphDb(
|
||||
nodeList: string[],
|
||||
filters: Record<string, any>,
|
||||
limit = 100,
|
||||
topK = 100,
|
||||
): Promise<SearchOutput[]> {
|
||||
const resultRelations: SearchOutput[] = [];
|
||||
const session = this.graph.session();
|
||||
@@ -344,7 +344,7 @@ export class MemoryGraph {
|
||||
n_embedding: nEmbedding,
|
||||
threshold: this.threshold,
|
||||
user_id: filters["userId"],
|
||||
limit: Math.floor(Number(limit)),
|
||||
limit: Math.floor(Number(topK)),
|
||||
});
|
||||
|
||||
resultRelations.push(
|
||||
|
||||
@@ -39,7 +39,7 @@ import { captureClientEvent } from "../utils/telemetry";
|
||||
|
||||
export class Memory {
|
||||
private config: MemoryConfig;
|
||||
private customPrompt: string | undefined;
|
||||
private customInstructions: string | undefined;
|
||||
private embedder: Embedder;
|
||||
private vectorStore!: VectorStore;
|
||||
private llm: LLM;
|
||||
@@ -56,7 +56,7 @@ export class Memory {
|
||||
// Merge and validate config
|
||||
this.config = ConfigManager.mergeConfig(config);
|
||||
|
||||
this.customPrompt = this.config.customPrompt;
|
||||
this.customInstructions = this.config.customInstructions;
|
||||
this.embedder = EmbedderFactory.create(
|
||||
this.config.embedder.provider,
|
||||
this.config.embedder.config,
|
||||
@@ -293,11 +293,11 @@ export class Memory {
|
||||
}
|
||||
const parsedMessages = messages.map((m) => m.content).join("\n");
|
||||
|
||||
const [systemPrompt, userPrompt] = this.customPrompt
|
||||
const [systemPrompt, userPrompt] = this.customInstructions
|
||||
? [
|
||||
this.customPrompt.toLowerCase().includes("json")
|
||||
? this.customPrompt
|
||||
: `${this.customPrompt}\n\nYou MUST return a valid JSON object with a 'facts' key containing an array of strings.`,
|
||||
this.customInstructions.toLowerCase().includes("json")
|
||||
? this.customInstructions
|
||||
: `${this.customInstructions}\n\nYou MUST return a valid JSON object with a 'facts' key containing an array of strings.`,
|
||||
`Input:\n${parsedMessages}`,
|
||||
]
|
||||
: getFactRetrievalMessages(parsedMessages);
|
||||
@@ -478,10 +478,10 @@ export class Memory {
|
||||
await this._ensureInitialized();
|
||||
await this._captureEvent("search", {
|
||||
query_length: query.length,
|
||||
limit: config.limit,
|
||||
topK: config.topK,
|
||||
has_filters: !!config.filters,
|
||||
});
|
||||
const { userId, agentId, runId, limit = 100, filters = {} } = config;
|
||||
const { userId, agentId, runId, topK = 100, filters = {} } = config;
|
||||
|
||||
if (userId) filters.userId = userId;
|
||||
if (agentId) filters.agentId = agentId;
|
||||
@@ -497,7 +497,7 @@ export class Memory {
|
||||
const queryEmbedding = await this.embedder.embed(query);
|
||||
const memories = await this.vectorStore.search(
|
||||
queryEmbedding,
|
||||
limit,
|
||||
topK,
|
||||
filters,
|
||||
);
|
||||
|
||||
@@ -642,19 +642,19 @@ export class Memory {
|
||||
async getAll(config: GetAllMemoryOptions): Promise<SearchResult> {
|
||||
await this._ensureInitialized();
|
||||
await this._captureEvent("get_all", {
|
||||
limit: config.limit,
|
||||
topK: config.topK,
|
||||
has_user_id: !!config.userId,
|
||||
has_agent_id: !!config.agentId,
|
||||
has_run_id: !!config.runId,
|
||||
});
|
||||
const { userId, agentId, runId, limit = 100 } = config;
|
||||
const { userId, agentId, runId, topK = 100 } = config;
|
||||
|
||||
const filters: SearchFilters = {};
|
||||
if (userId) filters.userId = userId;
|
||||
if (agentId) filters.agentId = agentId;
|
||||
if (runId) filters.runId = runId;
|
||||
|
||||
const [memories] = await this.vectorStore.list(filters, limit);
|
||||
const [memories] = await this.vectorStore.list(filters, topK);
|
||||
|
||||
const excludedKeys = new Set([
|
||||
"userId",
|
||||
|
||||
@@ -14,12 +14,12 @@ export interface AddMemoryOptions extends Entity {
|
||||
}
|
||||
|
||||
export interface SearchMemoryOptions extends Entity {
|
||||
limit?: number;
|
||||
topK?: number;
|
||||
filters?: SearchFilters;
|
||||
}
|
||||
|
||||
export interface GetAllMemoryOptions extends Entity {
|
||||
limit?: number;
|
||||
topK?: number;
|
||||
}
|
||||
|
||||
export interface DeleteAllMemoryOptions extends Entity {}
|
||||
|
||||
@@ -120,11 +120,11 @@ describe("backward compat: ConfigManager.mergeConfig", () => {
|
||||
expect(cfg.graphStore!.config.url).toBe("neo4j://custom:7687");
|
||||
});
|
||||
|
||||
it("customPrompt passes through unchanged", () => {
|
||||
it("customInstructions passes through unchanged", () => {
|
||||
const cfg = ConfigManager.mergeConfig({
|
||||
customPrompt: "You are a helpful assistant",
|
||||
customInstructions: "You are a helpful assistant",
|
||||
});
|
||||
expect(cfg.customPrompt).toBe("You are a helpful assistant");
|
||||
expect(cfg.customInstructions).toBe("You are a helpful assistant");
|
||||
});
|
||||
|
||||
it("version override passes through unchanged", () => {
|
||||
|
||||
@@ -60,7 +60,7 @@ export interface GraphStoreConfig {
|
||||
provider: string;
|
||||
config: Neo4jConfig;
|
||||
llm?: LLMConfig;
|
||||
customPrompt?: string;
|
||||
customInstructions?: string;
|
||||
}
|
||||
|
||||
export interface MemoryConfig {
|
||||
@@ -80,7 +80,7 @@ export interface MemoryConfig {
|
||||
historyStore?: HistoryStoreConfig;
|
||||
disableHistory?: boolean;
|
||||
historyDbPath?: string;
|
||||
customPrompt?: string;
|
||||
customInstructions?: string;
|
||||
graphStore?: GraphStoreConfig;
|
||||
enableGraph?: boolean;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ export const MemoryConfigSchema = z.object({
|
||||
}),
|
||||
}),
|
||||
historyDbPath: z.string().optional(),
|
||||
customPrompt: z.string().optional(),
|
||||
customInstructions: z.string().optional(),
|
||||
enableGraph: z.boolean().optional(),
|
||||
graphStore: z
|
||||
.object({
|
||||
@@ -164,7 +164,7 @@ export const MemoryConfigSchema = z.object({
|
||||
config: z.record(z.string(), z.any()),
|
||||
})
|
||||
.optional(),
|
||||
customPrompt: z.string().optional(),
|
||||
customInstructions: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
historyStore: z
|
||||
|
||||
@@ -331,7 +331,7 @@ export class AzureAISearch implements VectorStore {
|
||||
*/
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
const filterExpression = filters
|
||||
@@ -341,7 +341,7 @@ export class AzureAISearch implements VectorStore {
|
||||
const vectorQuery: VectorizedQuery<any> = {
|
||||
kind: "vector",
|
||||
vector: query,
|
||||
kNearestNeighborsCount: limit,
|
||||
kNearestNeighborsCount: topK,
|
||||
fields: ["vector"],
|
||||
};
|
||||
|
||||
@@ -355,7 +355,7 @@ export class AzureAISearch implements VectorStore {
|
||||
filterMode: this.vectorFilterMode as any,
|
||||
},
|
||||
filter: filterExpression,
|
||||
top: limit,
|
||||
top: topK,
|
||||
searchFields: ["payload"],
|
||||
});
|
||||
} else {
|
||||
@@ -366,7 +366,7 @@ export class AzureAISearch implements VectorStore {
|
||||
filterMode: this.vectorFilterMode as any,
|
||||
},
|
||||
filter: filterExpression,
|
||||
top: limit,
|
||||
top: topK,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ export class AzureAISearch implements VectorStore {
|
||||
*/
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
const filterExpression = filters
|
||||
? this.buildFilterExpression(filters)
|
||||
@@ -509,7 +509,7 @@ export class AzureAISearch implements VectorStore {
|
||||
|
||||
const searchResults = await this.searchClient.search("*", {
|
||||
filter: filterExpression,
|
||||
top: limit,
|
||||
top: topK,
|
||||
});
|
||||
|
||||
const results: VectorStoreResult[] = [];
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface VectorStore {
|
||||
): Promise<void>;
|
||||
search(
|
||||
query: number[],
|
||||
limit?: number,
|
||||
topK?: number,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]>;
|
||||
get(vectorId: string): Promise<VectorStoreResult | null>;
|
||||
@@ -21,7 +21,7 @@ export interface VectorStore {
|
||||
deleteCol(): Promise<void>;
|
||||
list(
|
||||
filters?: SearchFilters,
|
||||
limit?: number,
|
||||
topK?: number,
|
||||
): Promise<[VectorStoreResult[], number]>;
|
||||
getUserId(): Promise<string>;
|
||||
setUserId(userId: string): Promise<void>;
|
||||
|
||||
@@ -101,7 +101,7 @@ export class LangchainVectorStore implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters, // filters parameter is received but will be ignored
|
||||
): Promise<VectorStoreResult[]> {
|
||||
if (this.dimension && query.length !== this.dimension) {
|
||||
@@ -119,7 +119,7 @@ export class LangchainVectorStore implements VectorStore {
|
||||
// Call similaritySearchVectorWithScore WITHOUT the filter argument
|
||||
const results = await this.lcStore.similaritySearchVectorWithScore(
|
||||
query,
|
||||
limit,
|
||||
topK,
|
||||
// Do not pass lcFilter here
|
||||
);
|
||||
|
||||
@@ -192,7 +192,7 @@ export class LangchainVectorStore implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
// No standard list method in Langchain core interface.
|
||||
console.error(
|
||||
|
||||
@@ -100,7 +100,7 @@ export class MemoryVectorStore implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 10,
|
||||
topK: number = 10,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
if (query.length !== this.dimension) {
|
||||
@@ -136,7 +136,7 @@ export class MemoryVectorStore implements VectorStore {
|
||||
}
|
||||
|
||||
results.sort((a, b) => (b.score || 0) - (a.score || 0));
|
||||
return results.slice(0, limit);
|
||||
return results.slice(0, topK);
|
||||
}
|
||||
|
||||
async get(vectorId: string): Promise<VectorStoreResult | null> {
|
||||
@@ -179,7 +179,7 @@ export class MemoryVectorStore implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
const rows = this.db.prepare(`SELECT * FROM vectors`).all() as any[];
|
||||
const results: VectorStoreResult[] = [];
|
||||
@@ -206,7 +206,7 @@ export class MemoryVectorStore implements VectorStore {
|
||||
}
|
||||
}
|
||||
|
||||
return [results.slice(0, limit), results.length];
|
||||
return [results.slice(0, topK), results.length];
|
||||
}
|
||||
|
||||
async getUserId(): Promise<string> {
|
||||
|
||||
@@ -164,12 +164,12 @@ export class PGVector implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
const filterConditions: string[] = [];
|
||||
const queryVector = `[${query.join(",")}]`; // Format query vector as string with square brackets
|
||||
const filterValues: any[] = [queryVector, limit];
|
||||
const filterValues: any[] = [queryVector, topK];
|
||||
let filterIndex = 3;
|
||||
|
||||
if (filters) {
|
||||
@@ -254,7 +254,7 @@ export class PGVector implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
const filterConditions: string[] = [];
|
||||
const filterValues: any[] = [];
|
||||
@@ -286,7 +286,7 @@ export class PGVector implements VectorStore {
|
||||
${filterClause}
|
||||
`;
|
||||
|
||||
filterValues.push(limit); // Add limit as the last parameter
|
||||
filterValues.push(topK); // Add limit as the last parameter
|
||||
|
||||
const [listResult, countResult] = await Promise.all([
|
||||
this.client.query(listQuery, filterValues),
|
||||
|
||||
@@ -139,14 +139,14 @@ export class Qdrant implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
const queryFilter = this.createFilter(filters);
|
||||
const results = await this.client.search(this.collectionName, {
|
||||
vector: query,
|
||||
filter: queryFilter,
|
||||
limit,
|
||||
limit: topK,
|
||||
});
|
||||
|
||||
return results.map((hit) => ({
|
||||
@@ -198,10 +198,10 @@ export class Qdrant implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
const scrollRequest = {
|
||||
limit,
|
||||
limit: topK,
|
||||
filter: this.createFilter(filters),
|
||||
with_payload: true,
|
||||
with_vectors: false,
|
||||
|
||||
@@ -359,7 +359,7 @@ export class RedisDB implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
const snakeFilters = filters ? toSnakeCase(filters) : undefined;
|
||||
@@ -391,14 +391,14 @@ export class RedisDB implements VectorStore {
|
||||
DIALECT: 2,
|
||||
LIMIT: {
|
||||
from: 0,
|
||||
size: limit,
|
||||
size: topK,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const results = (await this.client.ft.search(
|
||||
this.indexName,
|
||||
`${filterExpr} =>[KNN ${limit} @embedding $vec AS __vector_score]`,
|
||||
`${filterExpr} =>[KNN ${topK} @embedding $vec AS __vector_score]`,
|
||||
searchOptions,
|
||||
)) as unknown as RedisSearchResult;
|
||||
|
||||
@@ -598,7 +598,7 @@ export class RedisDB implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
const snakeFilters = filters ? toSnakeCase(filters) : undefined;
|
||||
const filterExpr = snakeFilters
|
||||
@@ -613,7 +613,7 @@ export class RedisDB implements VectorStore {
|
||||
SORTDIR: "DESC",
|
||||
LIMIT: {
|
||||
from: 0,
|
||||
size: limit,
|
||||
size: topK,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -231,13 +231,13 @@ See the SQL migration instructions in the code comments.`,
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
try {
|
||||
const rpcQuery: VectorQueryParams = {
|
||||
query_embedding: query,
|
||||
match_count: limit,
|
||||
match_count: topK,
|
||||
};
|
||||
|
||||
if (filters) {
|
||||
@@ -336,13 +336,13 @@ See the SQL migration instructions in the code comments.`,
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 100,
|
||||
topK: number = 100,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
try {
|
||||
let query = this.client
|
||||
.from(this.tableName)
|
||||
.select("*", { count: "exact" })
|
||||
.limit(limit);
|
||||
.limit(topK);
|
||||
|
||||
if (filters) {
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
|
||||
@@ -76,7 +76,7 @@ export class VectorizeDB implements VectorStore {
|
||||
|
||||
async search(
|
||||
query: number[],
|
||||
limit: number = 5,
|
||||
topK: number = 5,
|
||||
filters?: SearchFilters,
|
||||
): Promise<VectorStoreResult[]> {
|
||||
try {
|
||||
@@ -87,7 +87,7 @@ export class VectorizeDB implements VectorStore {
|
||||
vector: query,
|
||||
filter: filters,
|
||||
returnMetadata: "all",
|
||||
topK: limit,
|
||||
topK: topK,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -197,7 +197,7 @@ export class VectorizeDB implements VectorStore {
|
||||
|
||||
async list(
|
||||
filters?: SearchFilters,
|
||||
limit: number = 20,
|
||||
topK: number = 20,
|
||||
): Promise<[VectorStoreResult[], number]> {
|
||||
try {
|
||||
const result = await this.client?.vectorize.indexes.query(
|
||||
@@ -206,7 +206,7 @@ export class VectorizeDB implements VectorStore {
|
||||
account_id: this.accountId,
|
||||
vector: Array(this.dimensions).fill(0), // Dummy vector for listing
|
||||
filter: filters,
|
||||
topK: limit,
|
||||
topK: topK,
|
||||
returnMetadata: "all",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -305,13 +305,15 @@ describe("_establishNodesRelationsFromData", () => {
|
||||
expect(systemContent).toContain("test-user");
|
||||
expect(systemContent).not.toContain("USER_ID");
|
||||
// CUSTOM_PROMPT placeholder stays when no custom prompt is configured
|
||||
// (only replaced when config.graphStore.customPrompt is set)
|
||||
// (only replaced when config.graphStore.customInstructions is set)
|
||||
});
|
||||
|
||||
it("appends JSON format suffix and custom prompt when configured", async () => {
|
||||
mockGenerateResponse.mockResolvedValueOnce({ toolCalls: [] });
|
||||
|
||||
const mg = graph({ customPrompt: "Focus on food relationships only." });
|
||||
const mg = graph({
|
||||
customInstructions: "Focus on food relationships only.",
|
||||
});
|
||||
await mg._establishNodesRelationsFromData("data", FILTERS, {});
|
||||
|
||||
const [messages] = mockGenerateResponse.mock.calls[0];
|
||||
|
||||
Reference in New Issue
Block a user