@streetjs/ai
v1.1.0
Published
Official Street Framework AI module: provider-agnostic chat, embeddings, RAG, and tool-calling with OpenAI/Anthropic/Ollama adapters and a deterministic in-memory provider for tests.
Maintainers
Readme
@streetjs/ai
Official StreetJS Framework AI module: a provider-agnostic surface for LLM chat, embeddings, retrieval-augmented generation (RAG), and tool calling.
- One
AiProvidercontract; swap implementations freely - Adapters:
OpenAiProvider,AnthropicProvider,OllamaProvider FakeAiProvider— deterministic, network-free; default for tests/offline devRagPipeline— embed → store → retrieve → answer (withInMemoryVectorStore)ChatSession— a tool-calling loop (model requests tools, you run handlers)
Install
npm install @streetjs/aiChat
import { OpenAiProvider } from '@streetjs/ai';
const ai = new OpenAiProvider({ apiKey: process.env.OPENAI_API_KEY });
const res = await ai.chat({ messages: [{ role: 'user', content: 'Hello!' }] });
console.log(res.message.content, res.usage);Swap providers without touching call sites:
import { AnthropicProvider, OllamaProvider } from '@streetjs/ai';
const claude = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
const local = new OllamaProvider({ baseUrl: 'http://127.0.0.1:11434' });Embeddings + RAG
import { RagPipeline, OpenAiProvider } from '@streetjs/ai';
const rag = new RagPipeline({ provider: new OpenAiProvider({ apiKey }), topK: 4 });
await rag.index([
{ id: 'd1', text: 'The Eiffel Tower is in Paris.' },
{ id: 'd2', text: 'Mount Everest is the tallest mountain.' },
]);
const { answer, context } = await rag.answer('Where is the Eiffel Tower?');Tool calling
import { ChatSession, OpenAiProvider } from '@streetjs/ai';
const session = new ChatSession({
provider: new OpenAiProvider({ apiKey }),
system: 'You can do arithmetic.',
tools: [{
name: 'add',
description: 'Add two numbers',
parameters: { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } } },
handler: ({ a, b }) => Number(a) + Number(b),
}],
});
const { message, toolCallsExecuted } = await session.send('what is 2 + 3?');
// session runs the tool, feeds the result back, and returns the final answerTesting without network
FakeAiProvider is deterministic and offline. Its embeddings are hashed
bag-of-words vectors, so lexically similar text scores higher — enough to
exercise RAG end-to-end in tests. The HTTP adapters accept an injectable
fetch, so request/response handling is unit-tested without real API calls.
import { FakeAiProvider, RagPipeline } from '@streetjs/ai';
const rag = new RagPipeline({ provider: new FakeAiProvider() });API
- Providers:
OpenAiProvider,AnthropicProvider,OllamaProvider,FakeAiProvider RagPipeline(index,retrieve,answer),InMemoryVectorStore,cosineSimilarity,hashEmbeddingChatSession(send,messages)- Types:
AiProvider,ChatRequest/Response,ChatMessage,ToolCall,ToolDefinition,EmbedRequest/Response
Notes
AnthropicProviderdoes not support embeddings (use OpenAI or Ollama).- Tool-call wiring is implemented for the OpenAI adapter; Anthropic/Ollama adapters cover chat + (Ollama) embeddings. Function-calling for those is a tracked follow-up.
Testing
npm run test -w packages/ai # unit + property tests, fully offlineLicense
MIT
