Skip to content

Commit d626fff

Browse files
authored
Aisdk (#56)
* refactor: Migrate to AI SDK and simplify LLM model handling - Updated package dependencies to use @AI-SDK libraries - Replaced Anthropic and OpenAI direct SDK implementations with ModelAdapter - Simplified LLM service to use a unified model generation approach - Updated tests to work with new ModelAdapter interface - Removed direct API key management from LLM classes * refactor: Simplify workflow and tool handling with AI SDK integration - Updated QueryOrchestrator to use AI SDK's ToolSet for tool management - Removed complex tool selection and processing logic - Simplified workflow to directly generate responses with available tools - Updated tests to reflect new workflow and LLM generation approach - Modified Tool interface to include AI SDK Tool schema * feat: Add Zod validation and AI SDK tool schemas for Nubila weather tools - Integrated Zod schema for validating latitude and longitude coordinates - Added AI SDK tool schemas for CurrentWeatherTool and ForecastWeatherTool - Updated BaseWeatherAPITool to include a schema property - Implemented tool method from AI SDK for both weather tools - Enhanced input validation and tool definition for weather-related tools * refactor: Update tool schema handling in QueryOrchestrator and Tool interface - Modified QueryOrchestrator's buildToolSet method to support multiple tool schemas - Updated Tool interface and APITool base class to use an array of tool schemas - Adjusted workflow and test files to accommodate the new schema structure - Simplified tool registration and schema management in the workflow process * refactor: Update BaseWeatherAPITool schema to support multiple tool definitions - Modified CurrentWeatherAPITool and ForecastWeatherAPITool to use an array of tool schemas - Updated schema property to include tool name and corresponding tool definition - Maintained consistency with previous refactoring of tool schema handling * feat: Add Zod schemas and AI SDK tool definitions for DimoTool - Integrated Zod schemas for list_vehicles, get_vehicle_signals, and get_latest_signals tools - Added AI SDK tool schemas with input validation and execution methods - Refactored DimoTool to support multiple tool definitions and dynamic tool execution - Exposed public methods for vehicle and signal retrieval - Simplified tool initialization and JWT management * feat: Enhance NewsAPI tool with Zod validation and AI SDK integration - Added Zod schemas for news categories and article validation - Implemented AI SDK tool schema for get_headlines with input parameters - Extended NewsAPITool to support category and keyword filtering - Improved error handling and response validation - Updated test suite to reflect new tool capabilities * feat: Enhance L1DataTool with Zod validation and AI SDK tool integration - Added Zod schemas for L1 chain statistics and GraphQL response validation - Implemented AI SDK tool schema for get_l1_stats with dynamic data processing - Added type inference using Zod schemas for improved type safety - Enhanced error handling and data validation in getRawData methods - Added descriptive schema descriptions for better tool documentation * feat: Enhance NuclearOutagesTool with Zod validation and AI SDK tool integration - Added Zod schemas for date range and nuclear outage data validation - Implemented AI SDK tool schema for get_nuclear_outages with summary statistics - Added type inference using Zod schemas for improved type safety - Enhanced input validation and error handling in date range processing - Added descriptive schema descriptions for better tool documentation - Integrated schema validation in getRawData and execute methods * feat: Enhance DePINScan tools with Zod validation and AI SDK tool integration - Added Zod schemas for DePIN metrics and projects with comprehensive field validation - Implemented AI SDK tool schemas for get_depin_metrics and get_depin_projects - Added type inference and validation for DePINScan data retrieval - Enhanced input parsing and data processing with Zod schema validation - Added descriptive schema descriptions for better tool documentation - Integrated AI SDK tool methods for metrics and projects retrieval * feat: Add Mapbox Geocoding tool with Zod validation and AI SDK integration - Implemented MapboxGeocodingTool with comprehensive Zod schemas for geocoding responses - Added AI SDK tool schema for get_coordinates with location and coordinate retrieval - Integrated Mapbox Geocoding API for converting location names to geographic coordinates - Implemented input parsing and error handling for geocoding requests - Added support for optional country, type, and result limit parameters - Registered Mapbox Geocoding tool in the ToolRegistry for easy access * feat: Expand Mapbox tool with directions and enhanced geocoding capabilities - Added comprehensive Zod schemas for route and directions data - Implemented new get_directions tool with support for multiple transportation profiles - Extended MapboxGeocodingTool to MapboxTool with geocoding and routing functionality - Added methods for geocoding locations and retrieving route details - Integrated AI-powered text parsing and response formatting for directions - Updated ToolRegistry to use the new MapboxTool class - Added logging and error handling for routing and geocoding requests * refactor: Rename Tool interface to QSTool and update type references - Renamed `Tool` interface to `QSTool` across multiple files - Removed unnecessary method signatures from tool interface - Simplified tool type definitions in various components - Updated imports and type references in tools, workflow, and core classes - Removed unused method signatures like `execute` and `parseInput` * refactor: Simplify Nubila weather tools and remove unnecessary abstractions - Removed complex formatting and parsing methods from BaseWeatherAPITool - Simplified CurrentWeatherAPITool and ForecastWeatherAPITool implementations - Removed Coordinates extraction class and related LLM-based coordinate parsing - Deleted redundant types file and moved type definitions inline - Updated tool names to more descriptive and consistent formats - Removed unnecessary method signatures and simplified tool schemas - Enhanced test coverage for simplified tool implementations * refactor: Simplify NewsAPI tool and remove unnecessary abstractions - Removed commented-out Zod schemas for NewsAPI response - Simplified NewsAPITool implementation with focused methods - Removed logger and error handling from execute method - Streamlined getRawData method to directly fetch and return news data - Updated test suite to reflect new tool implementation - Removed unnecessary method signatures and parsing logic * refactor: Simplify DimoTool and remove complex parsing methods - Removed execute, parseInput, and cleanData methods - Simplified getRawData method to handle different data retrieval scenarios - Updated tool schema initialization with more concise references - Removed unnecessary logging and LLM-based parsing logic - Enhanced type safety with DimoParams interface - Streamlined vehicle and signal retrieval methods - Updated test suite to reflect simplified tool implementation * refactor: Extract type definitions for Dimo and Nubila tools - Created new type definition files `src/tools/types/dimo.ts` and `src/tools/types/nubila.ts` - Moved existing type interfaces and type definitions from `dimo.ts` and `nubila.ts` to respective type files - Updated import statements in source files to use new type definition modules - Improved code organization by separating type definitions from tool implementations * refactor: Improve L1DataTool with enhanced error handling and tool schema - Updated L1DataTool to use more precise tool schema and description - Simplified constructor and schema initialization - Enhanced error handling in getRawData and sendRestRequest methods - Removed unnecessary execute and parseInput methods - Improved test coverage for error scenarios and data retrieval - Removed logger dependency and simplified error management * refactor: Simplify NuclearOutagesTool and remove complex parsing methods - Removed execute, parseInput, formatResponse, and validateDates methods - Simplified getRawData method to handle date range validation and API requests - Updated tool schema initialization with more concise references - Removed LLM-based input parsing and response formatting logic - Enhanced type safety with Zod schema validation - Updated test suite to reflect simplified tool implementation - Removed unnecessary imports and logger dependencies * refactor: Simplify Nubila tool type definitions and imports - Moved CoordinatesInput type definition from types file to nubila.ts - Removed redundant import of CoordinatesInput in nubila.ts - Cleaned up type definitions in nubila types file - Simplified type management for Nubila weather tools * refactor: Simplify DePINScan tools with enhanced error handling and type safety - Removed complex execute and parseInput methods from DePINScanMetricsTool and DePINScanProjectsTool - Simplified getRawData methods with direct Zod schema validation - Updated tool schemas with more concise and descriptive names - Enhanced error handling for API requests and network errors - Removed unnecessary LLM-based parsing and response formatting logic - Improved test coverage for error scenarios and data retrieval - Cleaned up imports and removed unused dependencies * feat: Add streaming endpoint for AI responses - Implemented `/stream` endpoint in server.ts to support streaming AI responses - Added `stream` method to SentientAI and QueryOrchestrator classes - Updated ModelAdapter to support text streaming with smooth word-based chunking - Integrated streaming functionality with existing AI workflow and tool processing - Added UUID generation for streaming message identification * refactor: Remove deprecated template files and test suites - Deleted `src/templates/index.ts` containing response and tool selection templates - Removed `src/templates/templates.test.ts` with associated test cases - Deleted `src/tools/templates.ts` containing DePIN scan project template - Cleaned up unused template and test files related to AI response generation * refactor: Enhance Mapbox tool with comprehensive geocoding and directions support - Completely refactored MapboxTool to support multiple geocoding operations - Added new methods for forward and reverse geocoding - Implemented robust coordinate parsing and validation - Enhanced error handling and input type safety - Added comprehensive test suite for all Mapbox tool methods - Removed deprecated execute and parsing methods - Simplified tool schema and initialization - Improved type definitions for geocoding and directions parameters * docs: Improve Dimo tool documentation and signal retrieval descriptions - Added example token ID to vehicle signals tool parameters - Enhanced description for get_latest_signals tool with usage note - Clarified that not all vehicles support all signals - Improved parameter descriptions for better user understanding * feat: Add ETHDenver events search tool to tool registry - Implemented ETHDenverTool for searching ETH Denver 2025 events - Created vector-based retrieval system using Qdrant and OpenAI embeddings - Added tool to ToolRegistry for dynamic tool loading - Supports semantic search across event documents with ParentDocumentRetriever * refactor: Simplify DePINScan and Nuclear Outages tools by removing Zod parsing - Removed Zod schema parsing from DePINScanMetricsTool and DePINScanProjectsTool - Simplified getRawData methods to return raw JSON directly - Updated NuclearOutagesTool to return raw data without Zod validation - Reduced unnecessary type parsing overhead in API response handling * refactor: Enhance logging with improved error context and metadata handling - Updated server.ts to add more descriptive error logging with context - Modified winston logger to support additional metadata in log messages - Added console.log for immediate error visibility - Implemented custom log format to include metadata in log entries - Improved error logging across different API endpoints (/ask, /stream, /raw) * feat: Add configurable system prompt for LLM interactions - Added support for custom system prompt via environment variable - Implemented fallback system prompt in ModelAdapter for text generation and streaming - Allows flexible configuration of AI assistant's initial context and behavior * chore: Update package dependencies for AI and vector search tools - Added LangChain, Qdrant, and Upstash Redis dependencies - Integrated OpenAI, Qdrant, and LangChain core libraries - Included logform for enhanced logging capabilities * chore: Update docker-compose configuration for ETHDenver deployment - Modified latest service to use qs:ethdenver image - Added new port mapping for frontend (33333:3000) - Commented out test service - Added new dimo service with qs:ethdenver image and unique port mapping * feat: Add Luma Events tool for fetching and parsing calendar events - Implemented LumaEventsTool to fetch and filter events from Luma calendars - Created custom iCalendar parser to extract event details - Added Luma tool to ToolRegistry for dynamic tool loading - Supports filtering events by title or description - Includes URL extraction and optional knowledge base storage * chore: Configure server idle timeout for improved connection management - Updated package.json scripts to include server idle timeout option - Set idle timeout to 120 seconds in server configuration - Ensures more robust connection handling and resource management * feat: Add support for parsing string coordinates in Nubila weather tool - Enhanced BaseWeatherAPITool to handle string latitude and longitude inputs - Added type conversion for string coordinates before Zod schema validation - Updated test suite to cover string coordinate parsing scenarios - Improved input flexibility for weather data retrieval * test: Remove redundant Zod validation tests from tools - Deleted schema validation tests for DePINMetricsTool, DePINProjectsTool, and NuclearOutagesTool - Simplified test suites by removing unnecessary Zod error checking - Maintains core functionality while reducing test complexity * feat: Add Claude 3.7 Sonnet model to supported Anthropic models - Updated ANTHROPIC_MODELS set in LLMService - Added latest Claude 3.7 Sonnet model to the supported models list * refactor: Enhance DePINScan tool with robust type handling and null value support - Updated DepinScanProjectSchema to handle nullable and optional fields - Added default values and flexible type parsing for project metrics - Improved category filtering with case-insensitive matching - Enhanced test coverage for edge cases with null and empty values - Implemented more resilient data transformation in project filtering * feat: Add current timestamp to system prompt for LLM context - Dynamically append current date and time to system prompt in both text generation and streaming methods - Ensures LLM has access to real-time temporal context - Maintains existing system prompt configuration with optional environment variable override * refactor: Remove optional filter parameter from Luma Events tool - Simplified Luma Events tool schema by removing unused filter parameter - Maintains core event fetching functionality - Reduces unnecessary complexity in tool configuration * feat: Enhance DePINScan tool with advanced project filtering - Added support for filtering projects by layer 1 blockchain - Implemented enum-based category filtering with predefined categories - Improved filtering logic to apply multiple filters sequentially - Updated test suite to validate new filtering capabilities * feat: Improve DePIN metrics data handling and test coverage - Enhanced DepinScanMetricsSchema to support mixed string/number types - Added null/undefined handling for metrics fields - Implemented robust parsing for volume, projects, market cap, and device metrics - Expanded test suite with scenarios for mixed data types and missing fields - Added comprehensive test cases for metrics transformation and edge cases * feat: Improve L1 data parsing and add robust error handling - Added quote removal for numeric API responses - Implemented TPS and numeric value parsing with improved precision - Enhanced error handling for API data retrieval - Added logging for GraphQL analytics stats - Exported GetL1StatsToolSchema for testing purposes - Updated test suite to handle quoted string responses * feat: Add comprehensive error handling and logging to tools - Imported logger from winston across multiple tools - Wrapped tool execution methods in try-catch blocks - Added error logging for each tool's execution method - Returned descriptive error messages when tool execution fails - Improved error resilience and debugging capabilities
1 parent 1f24885 commit d626fff

39 files changed

+3501
-1971
lines changed

docker-compose.yml

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,26 @@ services:
44
# CONFIG_PATH=configs/instance1.env docker compose up instance1
55

66
# Instance with all tools enabled (for testing)
7-
test:
8-
image: qs:main
9-
env_file: configs/.env.test
10-
ports:
11-
- "8000:8000"
12-
restart: always
7+
# test:
8+
# image: qs:main
9+
# env_file: configs/.env.test
10+
# ports:
11+
# - "8000:8000"
12+
# restart: always
1313

1414
# Template for production instances (commented out)
1515
latest:
16-
image: qs:latest
16+
image: qs:ethdenver
1717
env_file: configs/.env.latest
1818
ports:
19+
- "33333:3000"
1920
- "8000:8000"
2021
restart: always
2122

22-
# instance2:
23-
# image: qs:main
24-
# env_file: ${CONFIG_PATH}
25-
# ports:
26-
# - "8002:8000"
27-
# restart: always
23+
dimo:
24+
image: qs:ethdenver
25+
env_file: configs/.env.dimo
26+
ports:
27+
- "33334:3000"
28+
- "8001:8000"
29+
restart: always

package.json

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7-
"start": "bun run server.ts",
8-
"dev": "bun run --watch server.ts",
7+
"start": "bun run server.ts --server-options=\"{\\\"idleTimeout\\\": 120000}\"",
8+
"dev": "bun run --watch server.ts --server-options=\"{\\\"idleTimeout\\\": 120000}\"",
99
"test": "vitest run",
1010
"coverage": "vitest --coverage",
1111
"format": "bun prettier . --write"
@@ -14,16 +14,27 @@
1414
"author": "",
1515
"license": "ISC",
1616
"dependencies": {
17-
"@anthropic-ai/sdk": "^0.36.2",
17+
"@ai-sdk/anthropic": "^1.1.9",
18+
"@ai-sdk/deepseek": "^0.1.11",
19+
"@ai-sdk/openai": "^1.1.13",
1820
"@dimo-network/data-sdk": "^1.2.3",
21+
"ai": "^4.1.45",
1922
"axios": "^1.7.9",
2023
"chalk": "^4.1.2",
2124
"dotenv": "^16.4.7",
2225
"ethers": "^6.13.5",
2326
"hono": "^4.6.16",
24-
"openai": "^4.80.1",
27+
"logform": "^2.7.0",
2528
"typescript": "^5.7.2",
26-
"winston": "^3.17.0"
29+
"winston": "^3.17.0",
30+
"zod": "^3.24.2",
31+
"@qdrant/js-client-rest": "^1.13.0",
32+
"@langchain/qdrant": "^0.1.1",
33+
"@upstash/redis": "^1.34.4",
34+
"@langchain/community": "^0.3.32",
35+
"@langchain/core": "^0.3.40",
36+
"@langchain/openai": "^0.4.4",
37+
"langchain": "^0.3.19"
2738
},
2839
"devDependencies": {
2940
"@types/axios": "^0.14.4",

server.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,29 @@ app.post("/ask", async (c) => {
2929
const response = await sentai.execute(content);
3030
return c.json({ data: response });
3131
} catch (e) {
32-
logger.error(e);
32+
console.log("error", e);
33+
logger.error("Error in /ask", { error: e });
34+
return c.json({ error: "Internal server error." }, 400);
35+
}
36+
});
37+
38+
app.post("/stream", async (c) => {
39+
const apiKey = c.req.header("API-KEY");
40+
if (!apiKey) {
41+
logger.warn("no SENTAI API-KEY provided");
42+
}
43+
44+
try {
45+
const formData = await c.req.formData();
46+
let content = formData.get("text");
47+
const recentMessages = formData.get("recentMessages");
48+
if (recentMessages) {
49+
content = recentMessages + "\n" + content;
50+
}
51+
return sentai.stream(content as string);
52+
} catch (e) {
53+
console.log("error", e);
54+
logger.error("Error in /stream", { error: e });
3355
return c.json({ error: "Internal server error." }, 400);
3456
}
3557
});
@@ -57,12 +79,14 @@ app.get("/raw", async (c) => {
5779
const rawData = await sentai.getRawData(toolName, params);
5880
return c.json({ data: rawData });
5981
} catch (e: any) {
60-
logger.error(e);
82+
console.log("error", e);
83+
logger.error("Error in /raw", { error: e });
6184
return c.json({ error: e.message || "Internal server error" }, 500);
6285
}
6386
});
6487

6588
export default {
6689
port: process.env.PORT || 8000,
6790
fetch: app.fetch,
91+
idleTimeout: 120,
6892
};

src/__tests__/SentientAI.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { SentientAI } from "../sentientAI";
44

55
const currentWeatherOutput = `
66
<response>
7-
["CurrentWeatherAPITool"]
7+
["get_current_weather"]
88
</response>
99
`;
1010

@@ -19,29 +19,27 @@ describe("SentientAI", () => {
1919
generate: vi.fn().mockResolvedValue(currentWeatherOutput),
2020
},
2121
llm: {
22-
generate: vi.fn().mockResolvedValue("<response>+10 C</response>"),
22+
generate: vi.fn().mockResolvedValue("+10 C"),
2323
},
2424
})),
2525
}));
2626
vi.mock("../tools/weather/nubila", () => ({
2727
CurrentWeatherAPITool: vi.fn().mockImplementation(() => ({
28-
name: "CurrentWeatherAPITool",
28+
name: "get_current_weather",
2929
description:
3030
"Gets the current weather from Nubila API. Input is json with latitude and longitude to retrieve weather data.",
3131
twitterAccount: "nubilanetwork",
32-
execute: vi.fn().mockResolvedValue("+10 C"),
3332
})),
3433
ForecastWeatherAPITool: vi.fn().mockImplementation(() => ({
3534
name: "ForecastWeatherAPITool",
3635
description:
3736
"Gets the forecast weather from Nubila API. Input is json with latitude and longitude to retrieve weather data.",
38-
execute: vi.fn().mockResolvedValue("+10 C"),
3937
})),
4038
}));
4139
vi.mock("../raw-data-provider", () => ({
4240
RawDataProvider: vi.fn().mockImplementation(() => ({
4341
process: vi.fn().mockImplementation((tool, params) => {
44-
if (tool.name === "CurrentWeatherAPITool") {
42+
if (tool.name === "get_current_weather") {
4543
return Promise.resolve("+10 C");
4644
}
4745
return Promise.reject(new Error(`Unknown tool ${tool.name}`));

src/__tests__/workflow.test.ts

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ import { mockLLMService } from "./mocks";
22
import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
33

44
import { QueryOrchestrator } from "../workflow";
5-
import { CurrentWeatherAPITool, ForecastWeatherAPITool } from "../tools/nubila";
5+
import { CurrentWeatherAPITool } from "../tools/nubila";
66
import { LLMService } from "../llm/llm-service";
77
import { APITool } from "../tools/tool";
8+
import { Tool } from "ai";
89

910
class TestAPITool extends APITool<any> {
11+
schema: { name: string; tool: Tool }[] = [];
12+
1013
async execute(_: string): Promise<string> {
1114
return "<response>test</response>";
1215
}
1316

1417
async parseInput(_: string): Promise<any> {
1518
return "test";
1619
}
20+
21+
async getRawData(_: any): Promise<any> {
22+
return "test";
23+
}
1724
}
1825

1926
describe("Workflow", () => {
@@ -31,7 +38,7 @@ describe("Workflow", () => {
3138
generate: vi.fn().mockResolvedValue(queryResponse),
3239
},
3340
llm: {
34-
generate: vi.fn().mockResolvedValue("<response>+10 C</response>"),
41+
generate: vi.fn().mockResolvedValue("+10 C"),
3542
},
3643
}));
3744
};
@@ -82,58 +89,13 @@ describe("Workflow", () => {
8289
}),
8390
});
8491
const res = await workflow.process(
85-
"Rephrase the following sentence'Current temperature in SF?'",
92+
"Rephrase the following sentence'Current temperature in SF?'"
8693
);
8794
expect(res).toBe("What is the weather in SF?");
8895
});
8996
});
90-
describe("selectTools", () => {
91-
it("should return correct single tool", async () => {
92-
const workflow = new QueryOrchestrator({
93-
tools: [tool],
94-
llmService: new LLMService({
95-
fastLLMModel: "deepseek-chat",
96-
LLMModel: "deepseek-chat",
97-
}),
98-
});
99-
const res = await workflow.selectTools("Current temperature in SF?");
100-
101-
expect(res.length).toEqual(1);
102-
expect(res[0].name).toEqual("Test Tool");
103-
expect(res[0].description).toEqual("A test tool");
104-
expect(res[0].execute).toBeDefined();
105-
});
106-
it("should return correct multiple tools", async () => {
107-
// @ts-ignore no need to mock private methods
108-
vi.mocked(LLMService).mockImplementationOnce(() => ({
109-
fastllm: {
110-
generate: vi.fn().mockResolvedValue(multipleTools),
111-
},
112-
llm: {
113-
generate: vi.fn().mockResolvedValue("+10 C"),
114-
},
115-
}));
116-
const workflow = new QueryOrchestrator({
117-
tools: [new CurrentWeatherAPITool(), new ForecastWeatherAPITool()],
118-
llmService: new LLMService({
119-
fastLLMModel: "deepseek-chat",
120-
LLMModel: "deepseek-chat",
121-
}),
122-
});
123-
const res = await workflow.selectTools("Current temperature in SF?");
124-
125-
expect(res.length).toEqual(2);
126-
expect(res[0].name).toEqual("CurrentWeatherAPITool");
127-
expect(res[1].name).toEqual("ForecastWeatherAPITool");
128-
});
129-
});
13097
});
13198

132-
const multipleTools = `
133-
<response>
134-
["CurrentWeatherAPITool", "ForecastWeatherAPITool"]
135-
</response>
136-
`;
13799
const noTools = `
138100
<response>
139101
[]

src/llm/llm-service.test.ts

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect, beforeEach, afterAll } from "vitest";
22
import { LLMService } from "./llm-service";
3-
import { AnthropicLLM, OpenAILLM, DummyLLM } from "./llm";
3+
import { ModelAdapter } from "./llm";
44

55
// Mock environment variables
66
const originalEnv = process.env;
@@ -21,55 +21,48 @@ describe("LLMService", () => {
2121
LLMModel: "claude-3-5-sonnet-latest",
2222
});
2323

24-
expect(service.fastllm).toBeInstanceOf(AnthropicLLM);
25-
expect(service.llm).toBeInstanceOf(AnthropicLLM);
26-
expect((service.fastllm as AnthropicLLM).model).toBe(
27-
"claude-3-5-haiku-latest",
24+
expect((service.fastllm as ModelAdapter).model.modelId).toBe(
25+
"claude-3-5-haiku-latest"
2826
);
29-
expect((service.llm as AnthropicLLM).model).toBe(
30-
"claude-3-5-sonnet-latest",
27+
expect((service.llm as ModelAdapter).model.modelId).toBe(
28+
"claude-3-5-sonnet-latest"
3129
);
3230
});
3331

3432
it("should initialize with OpenAI models", () => {
35-
process.env.OPENAI_API_KEY = "test-key";
3633
const service = new LLMService({
3734
fastLLMModel: "gpt-4o",
3835
LLMModel: "gpt-4o-mini",
3936
});
4037

41-
expect(service.fastllm).toBeInstanceOf(OpenAILLM);
42-
expect(service.llm).toBeInstanceOf(OpenAILLM);
43-
expect((service.fastllm as OpenAILLM).model).toBe("gpt-4o");
44-
expect((service.llm as OpenAILLM).model).toBe("gpt-4o-mini");
38+
expect((service.fastllm as ModelAdapter).model.modelId).toBe("gpt-4o");
39+
expect((service.llm as ModelAdapter).model.modelId).toBe("gpt-4o-mini");
4540
});
4641

4742
it("should initialize with Deepseek models", () => {
48-
process.env.OPENAI_API_KEY = "test-key";
4943
const service = new LLMService({
5044
fastLLMModel: "deepseek-chat",
5145
LLMModel: "deepseek-reasoner",
5246
});
5347

54-
expect(service.fastllm).toBeInstanceOf(OpenAILLM);
55-
expect(service.llm).toBeInstanceOf(OpenAILLM);
56-
expect((service.fastllm as OpenAILLM).model).toBe("deepseek-chat");
57-
expect((service.llm as OpenAILLM).model).toBe("deepseek-reasoner");
48+
expect((service.fastllm as ModelAdapter).model.modelId).toBe(
49+
"deepseek-chat"
50+
);
51+
expect((service.llm as ModelAdapter).model.modelId).toBe(
52+
"deepseek-reasoner"
53+
);
5854
});
5955

6056
it("should mix different providers based on models", () => {
61-
process.env.LLM_API_KEY = "test-key";
6257
const service = new LLMService({
6358
fastLLMModel: "claude-3-5-haiku-latest",
6459
LLMModel: "gpt-4o",
6560
});
6661

67-
expect(service.fastllm).toBeInstanceOf(AnthropicLLM);
68-
expect(service.llm).toBeInstanceOf(OpenAILLM);
69-
expect((service.fastllm as AnthropicLLM).model).toBe(
70-
"claude-3-5-haiku-latest",
62+
expect((service.fastllm as ModelAdapter).model.modelId).toBe(
63+
"claude-3-5-haiku-latest"
7164
);
72-
expect((service.llm as OpenAILLM).model).toBe("gpt-4o");
65+
expect((service.llm as ModelAdapter).model.modelId).toBe("gpt-4o");
7366
});
7467
});
7568
});

src/llm/llm-service.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { LLM, AnthropicLLM, OpenAILLM, DummyLLM } from "./llm";
1+
import { LLM, ModelAdapter, DummyLLM } from "./llm";
22

33
const OPENAI_MODELS = new Set(["gpt-4o", "gpt-4o-mini", "o3-mini", "o1-mini"]);
44
const DEEPSEEK_MODELS = new Set(["deepseek-chat", "deepseek-reasoner"]);
55
const ANTHROPIC_MODELS = new Set([
66
"claude-3-5-sonnet-latest",
77
"claude-3-5-haiku-latest",
8+
"claude-3-7-sonnet-latest",
89
]);
910

1011
export class LLMService {
@@ -23,19 +24,19 @@ export class LLMService {
2324

2425
providerMap: Record<string, (model?: string) => LLM> = {
2526
anthropic: (model) =>
26-
new AnthropicLLM({
27+
new ModelAdapter({
28+
provider: "anthropic",
2729
model: model || "claude-3-5-haiku-latest",
2830
}),
2931
deepseek: (model) =>
30-
new OpenAILLM({
32+
new ModelAdapter({
33+
provider: "deepseek",
3134
model: model || "deepseek-chat",
32-
apiKey: process.env.DEEPSEEK_API_KEY || "",
33-
baseURL: "https://api.deepseek.com",
3435
}),
3536
openai: (model) =>
36-
new OpenAILLM({
37+
new ModelAdapter({
38+
provider: "openai",
3739
model: model || "gpt-4o-mini",
38-
apiKey: process.env.OPENAI_API_KEY || "",
3940
}),
4041
};
4142

0 commit comments

Comments
 (0)