TypeScript SDK 指南
使用 Hindsight TypeScript/JavaScript SDK 进行记忆操作的完整指南。
安装
- npm
- Yarn
- pnpm
npm install @vectorize-io/hindsight-client
yarn add @vectorize-io/hindsight-client
pnpm add @vectorize-io/hindsight-client
快速开始
import { HindsightClient } from '@vectorize-io/hindsight-client';
// Initialize the client
const client = new HindsightClient({
baseUrl: 'https://api.hindsight.vectorize.io',
apiKey: 'your-api-key'
});
async function main() {
// Create a memory bank
const bank = await client.createBank('my-assistant', {
name: 'My Assistant'
});
// Store a memory
await client.retain(
'my-assistant',
'The user prefers concise responses and dark mode.'
);
// Retrieve memories
const recallResult = await client.recall(
'my-assistant',
"What are the user's preferences?"
);
recallResult.results.forEach(memory => {
console.log(memory.text);
});
// Get an AI-powered answer
const response = await client.reflect(
'my-assistant',
'How should I format my responses for this user?'
);
console.log(response.text);
}
main();
客户端配置
基本配置
import { HindsightClient } from '@vectorize-io/hindsight-client';
const client = new HindsightClient({
baseUrl: 'https://api.hindsight.vectorize.io',
apiKey: 'your-api-key'
});
环境变量
const client = new HindsightClient({
baseUrl: process.env.HINDSIGHT_BASE_URL!,
apiKey: process.env.HINDSIGHT_API_KEY!
});
类型定义
SDK 是完全类型化的。以下是关键接口:
interface RecallResponse {
results: RecallResult[];
entities?: Entity[];
trace?: TraceInfo;
chunks?: Chunk[];
}
interface RecallResult {
text: string;
type: 'world' | 'experience' | 'observation';
// Additional metadata fields
}
interface ReflectResponse {
text: string;
based_on: BasedOnItem[];
structured_output?: Record<string, unknown>;
usage?: {
input_tokens: number;
output_tokens: number;
total_tokens: number;
};
}
interface BankProfileResponse {
bank_id: string;
name?: string;
background?: string;
disposition?: {
skepticism: number;
literalism: number;
empathy: number;
};
}
记忆库
创建记忆库
const bank = await client.createBank('customer-support-agent', {
name: 'Customer Support Agent',
background: 'This agent handles customer inquiries for an e-commerce platform',
disposition: {
skepticism: 3,
literalism: 2,
empathy: 4
}
});
console.log(`Created bank: ${bank.bank_id}`);
获取记忆库资料
const profile = await client.getBankProfile('my-assistant');
console.log(`Bank name: ${profile.name}`);
列出记忆库中的记忆
const result = await client.listMemories('my-assistant', {
limit: 100,
offset: 0
});
console.log(`Total memories: ${result.total}`);
result.items.forEach(memory => {
console.log(`- ${memory}`);
});
Retain(存储记忆)
基本用法
await client.retain(
'my-assistant',
'User mentioned they work remotely and prefer async communication.'
);
带选项
await client.retain(
'my-assistant',
'Customer reported a bug with the checkout process.',
{
context: 'Support ticket conversation',
timestamp: new Date(),
metadata: {
ticketId: 'TKT-12345',
priority: 'high'
}
}
);
批量操作
const items = [
{ content: 'User is based in Pacific timezone' },
{ content: 'User prefers email over phone calls' },
{ content: 'User has been a customer for 3 years' }
];
await client.retainBatch('my-assistant', items);
异步批量操作
// For large batches, use async processing
await client.retainBatch('my-assistant', items, {
async: true
});
Recall(搜索记忆)
基础搜索
const result = await client.recall(
'my-assistant',
'What communication preferences does the user have?'
);
result.results.forEach(memory => {
console.log(`[${memory.type}] ${memory.text}`);
});
带选项
// Limit results and set search budget
const result = await client.recall(
'my-assistant',
'project deadlines',
{
maxTokens: 4096,
budget: 'mid' // 'low', 'mid', or 'high'
}
);
// Filter by memory type
const observations = await client.recall(
'my-assistant',
'user preferences',
{
types: ['observation']
}
);
包含实体信息
const result = await client.recall(
'my-assistant',
'Tell me about Alice',
{
includeEntities: true,
maxEntityTokens: 1000
}
);
// Access entities
if (result.entities) {
result.entities.forEach(entity => {
console.log(`Entity: ${entity}`);
});
}
处理结果
const result = await client.recall('my-assistant', 'user info');
if (result.results.length === 0) {
console.log('No relevant memories found');
} else {
result.results.forEach(memory => {
console.log(`Type: ${memory.type}`);
console.log(`Content: ${memory.text}`);
console.log('---');
});
}
Reflect(在记忆之上推理)
基本查询
const response = await client.reflect(
'my-assistant',
'What should I know about this customer before our call?'
);
console.log(response.text);
带选项
const response = await client.reflect(
'my-assistant',
'What are their main pain points?',
{
context: "We're preparing for a product review meeting",
budget: 'high' // 'low', 'mid', or 'high'
}
);
console.log(response.text);
// Access source memories
response.based_on.forEach(source => {
console.log(`Based on: ${source}`);
});
Token 使用
const response = await client.reflect(
'my-assistant',
'Summarize our relationship'
);
if (response.usage) {
console.log(`Total tokens: ${response.usage.total_tokens}`);
}
心智模型
心智模型是用户精心整理的、预计算的反思,会随着新记忆的添加保持最新。它们通过运行 reflect 查询生成,并可在观察整合后自动刷新。
创建心智模型
// Creation runs asynchronously via reflect
const result = await client.createMentalModel(
'my-assistant',
'User Profile',
'What do we know about this user?'
);
console.log(`Operation ID: ${result.operation_id}`);
带选项创建
const result = await client.createMentalModel(
'my-assistant',
'Team Directory',
'Who works here and what do they do?',
{
tags: ['team', 'directory'],
maxTokens: 4096,
trigger: { refreshAfterConsolidation: true }
}
);
列出心智模型
const models = await client.listMentalModels('my-assistant');
models.items.forEach(model => {
console.log(`${model.name}: ${model.content?.substring(0, 100)}...`);
});
// Filter by tags
const filtered = await client.listMentalModels('my-assistant', {
tags: ['team']
});
获取心智模型
const model = await client.getMentalModel('my-assistant', 'mm_abc123');
console.log(`Name: ${model.name}`);
console.log(`Content: ${model.content}`);
console.log(`Last refreshed: ${model.last_refreshed_at}`);
刷新心智模型
// Re-run the source query to update the content
const result = await client.refreshMentalModel('my-assistant', 'mm_abc123');
console.log(`Refresh operation: ${result.operation_id}`);
更新心智模型
const model = await client.updateMentalModel('my-assistant', 'mm_abc123', {
name: 'Updated Profile',
sourceQuery: 'What are the user\'s key preferences?',
trigger: { refreshAfterConsolidation: true }
});
删除心智模型
await client.deleteMentalModel('my-assistant', 'mm_abc123');
错误处理
import { HindsightClient } from '@vectorize-io/hindsight-client';
const client = new HindsightClient({
baseUrl: 'https://api.hindsight.vectorize.io',
apiKey: 'your-api-key'
});
try {
const result = await client.recall('invalid-bank', 'test');
} catch (error) {
console.error('Error:', error.message);
}
常见 HTTP 错误
| 状态码 | 原因 | 解决方法 |
|---|---|---|
| 401 | API 密钥无效 | 检查 API 密钥 |
| 402 | 额度不足 | 为账户添加额度 |
| 404 | bank_id 无效 | 确认记忆库存在 |
| 400 | 请求无效 | 检查请求参数 |
框架集成
Next.js
// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { HindsightClient } from '@vectorize-io/hindsight-client';
const client = new HindsightClient({
baseUrl: process.env.HINDSIGHT_BASE_URL!,
apiKey: process.env.HINDSIGHT_API_KEY!
});
export async function POST(request: NextRequest) {
const { bankId, message } = await request.json();
// Store the user message
await client.retain(bankId, `User said: ${message}`);
// Get relevant context
const memories = await client.recall(bankId, message, { limit: 5 });
// Generate a response
const response = await client.reflect(
bankId,
`Based on our conversation history, respond to: ${message}`
);
return NextResponse.json({ response: response.text });
}
Express
import express from 'express';
import { HindsightClient } from '@vectorize-io/hindsight-client';
const app = express();
const client = new HindsightClient({
baseUrl: process.env.HINDSIGHT_BASE_URL!,
apiKey: process.env.HINDSIGHT_API_KEY!
});
app.use(express.json());
app.post('/api/memory', async (req, res) => {
const { bankId, content } = req.body;
try {
await client.retain(bankId, content);
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: 'Failed to store memory' });
}
});
app.get('/api/search', async (req, res) => {
const { bankId, query } = req.query as { bankId: string; query: string };
try {
const result = await client.recall(bankId, query);
res.json({ memories: result.results });
} catch (error) {
res.status(500).json({ error: 'Search failed' });
}
});
app.listen(3000);
最佳实践
单例模式
创建一个单例的客户端实例:
// lib/hindsight.ts
import { HindsightClient } from '@vectorize-io/hindsight-client';
let client: HindsightClient | null = null;
export function getHindsightClient(): HindsightClient {
if (!client) {
client = new HindsightClient({
baseUrl: process.env.HINDSIGHT_BASE_URL!,
apiKey: process.env.HINDSIGHT_API_KEY!
});
}
return client;
}
类型安全的元数据
interface TicketMetadata {
ticketId: string;
priority: 'low' | 'medium' | 'high';
customerId: string;
}
await client.retain(
'my-assistant',
'Customer issue description',
{
metadata: {
ticketId: 'TKT-123',
priority: 'high',
customerId: 'cust_abc'
} satisfies TicketMetadata
}
);
优雅降级
async function getContext(bankId: string, query: string): Promise<string> {
try {
const result = await client.recall(bankId, query, { limit: 3 });
return result.results.map(m => m.text).join('\n');
} catch (error) {
console.error('Failed to get context:', error);
return ''; // Return empty context on failure
}
}
完整示例
import { HindsightClient } from '@vectorize-io/hindsight-client';
async function main() {
const client = new HindsightClient({
baseUrl: process.env.HINDSIGHT_BASE_URL!,
apiKey: process.env.HINDSIGHT_API_KEY!
});
try {
const bankId = 'demo-assistant';
// Create a memory bank
const bank = await client.createBank(bankId, {
name: 'Demo Assistant',
disposition: {
skepticism: 3,
literalism: 2,
empathy: 4
}
});
console.log(`Using bank: ${bank.bank_id}`);
// Store some memories
const memoriesToStore = [
"User's name is Alice and she is a product manager",
'Alice prefers bullet points over long paragraphs',
'Alice works at TechCorp and manages the mobile team',
"Alice mentioned she's interested in AI automation"
];
for (const content of memoriesToStore) {
await client.retain(bankId, content);
console.log(`Stored: ${content.substring(0, 50)}...`);
}
// Search for relevant memories
const result = await client.recall(
bankId,
'What does Alice do for work?'
);
console.log('\nRelevant memories:');
result.results.forEach(memory => {
console.log(` - ${memory.text}`);
});
// Get an AI-synthesized answer
const response = await client.reflect(
bankId,
'Write a brief introduction for Alice'
);
console.log(`\nAI Response:\n${response.text}`);
} catch (error) {
console.error(`Error: ${error.message}`);
}
}
main();