@pioneer-platform/pioneer-inference 1.0.0 → 1.0.1

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.
@@ -0,0 +1 @@
1
+ $ tsc
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @pioneer-platform/pioneer-inference
2
+
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix workspace dependencies to use published versions for Docker build compatibility
package/README.md CHANGED
@@ -1,144 +1,217 @@
1
- # @pioneer-platform/pioneer-inference
1
+ # Pioneer Inference
2
2
 
3
- LLM inference abstraction layer for the Pioneer platform. Provides a unified interface for working with multiple LLM providers (OpenAI, Anthropic, Ollama, etc.).
3
+ OpenAI-compatible inference proxy for the Pioneer platform. This module provides a secure way to expose AI inference capabilities to your apps without exposing API keys.
4
+
5
+ ## Features
6
+
7
+ - **API Key Protection**: Keep your AI provider API keys secure on the server
8
+ - **System Prompt Injection**: Automatically inject system prompts to guide model behavior
9
+ - **Multi-Provider Support**: Works with OpenAI, OpenRouter, and Venice.ai
10
+ - **OpenAI-Compatible API**: Drop-in replacement for OpenAI client libraries
4
11
 
5
12
  ## Installation
6
13
 
7
- ```bash
8
- npm install @pioneer-platform/pioneer-inference
14
+ This is a workspace package in the Pioneer monorepo. It's automatically available to other packages via:
15
+
16
+ ```typescript
17
+ import { InferenceService, createInferenceServiceFromEnv } from '@pioneer-platform/pioneer-inference';
9
18
  ```
10
19
 
11
- ## Usage
20
+ ## Configuration
12
21
 
13
- ### Basic Usage
22
+ Set the following environment variables:
14
23
 
15
- ```typescript
16
- import { InferenceClient } from '@pioneer-platform/pioneer-inference';
24
+ ```bash
25
+ # Provider selection (openai, openrouter, or venice)
26
+ INFERENCE_PROVIDER=openai
17
27
 
18
- const client = new InferenceClient({
19
- provider: 'openai',
20
- apiKey: process.env.OPENAI_API_KEY,
21
- });
28
+ # API key for the selected provider
29
+ INFERENCE_API_KEY=your-api-key-here
30
+ # Or use the standard OpenAI key
31
+ OPENAI_API_KEY=your-api-key-here
32
+
33
+ # Optional: Custom base URL (for self-hosted or proxy endpoints)
34
+ INFERENCE_BASE_URL=https://api.openai.com/v1
22
35
 
23
- // Set system prompt
24
- client.setSystemPrompt('You are a helpful coding assistant.');
36
+ # Optional: System prompt to inject in all requests
37
+ INFERENCE_SYSTEM_PROMPT="You are a helpful cryptocurrency wallet assistant."
25
38
 
26
- // Send a message
27
- const response = await client.chat('Help me write a function');
28
- console.log(response);
39
+ # Optional: Default model to use
40
+ INFERENCE_DEFAULT_MODEL=gpt-4-turbo-preview
29
41
  ```
30
42
 
31
- ### Point to Custom Endpoint
43
+ ## Provider Configuration
32
44
 
33
- ```typescript
34
- const client = new InferenceClient({
35
- provider: 'openai',
36
- apiKey: 'any-key',
37
- baseURL: 'http://127.0.0.1:9101/v1', // Your custom OpenAI-compatible endpoint
38
- defaultModel: 'gpt-4-turbo-preview',
39
- });
45
+ ### OpenAI
46
+ ```bash
47
+ INFERENCE_PROVIDER=openai
48
+ INFERENCE_API_KEY=sk-...
49
+ # Default model: gpt-4-turbo-preview
40
50
  ```
41
51
 
42
- ### Using with Pioneer Server
52
+ ### OpenRouter
53
+ ```bash
54
+ INFERENCE_PROVIDER=openrouter
55
+ INFERENCE_API_KEY=sk-or-...
56
+ INFERENCE_BASE_URL=https://openrouter.ai/api/v1
57
+ # Default model: anthropic/claude-3-opus
58
+ ```
43
59
 
44
- ```typescript
45
- import { InferenceClient } from '@pioneer-platform/pioneer-inference';
60
+ ### Venice.ai
61
+ ```bash
62
+ INFERENCE_PROVIDER=venice
63
+ INFERENCE_API_KEY=your-venice-key
64
+ INFERENCE_BASE_URL=https://api.venice.ai/api/v1
65
+ # Default model: llama-3.1-405b
66
+ ```
46
67
 
47
- // Point to pioneer-server's OpenAI-compatible endpoint
48
- const client = new InferenceClient({
49
- provider: 'openai',
50
- apiKey: 'not-used', // Pioneer server handles auth differently
51
- baseURL: 'http://127.0.0.1:9101/v1',
52
- });
68
+ ## Usage
69
+
70
+ ### REST API Endpoints
71
+
72
+ The Pioneer server exposes OpenAI-compatible endpoints at `/v1`:
53
73
 
54
- const response = await client.chat('What can you help me with?');
74
+ #### Create Chat Completion
75
+ ```bash
76
+ POST http://localhost:9001/v1/chat/completions
77
+ Content-Type: application/json
78
+
79
+ {
80
+ "model": "gpt-4-turbo-preview",
81
+ "messages": [
82
+ {
83
+ "role": "user",
84
+ "content": "What is Bitcoin?"
85
+ }
86
+ ],
87
+ "temperature": 0.7,
88
+ "max_tokens": 150
89
+ }
55
90
  ```
56
91
 
57
- ### Full Control with Chat Completions
92
+ #### List Available Models
93
+ ```bash
94
+ GET http://localhost:9001/v1/models
95
+ ```
96
+
97
+ #### Get Provider Info
98
+ ```bash
99
+ GET http://localhost:9001/v1/provider
100
+ ```
101
+
102
+ Response:
103
+ ```json
104
+ {
105
+ "provider": "openai",
106
+ "hasSystemPrompt": true,
107
+ "configured": true
108
+ }
109
+ ```
110
+
111
+ ### Using in TypeScript
58
112
 
59
113
  ```typescript
60
- const response = await client.chatCompletion({
114
+ import { InferenceService } from '@pioneer-platform/pioneer-inference';
115
+
116
+ // Create service with custom configuration
117
+ const service = new InferenceService({
118
+ provider: 'openai',
119
+ apiKey: 'sk-...',
120
+ systemPrompt: 'You are a crypto assistant.',
121
+ defaultModel: 'gpt-4-turbo-preview'
122
+ });
123
+
124
+ // Create chat completion
125
+ const response = await service.createChatCompletion({
61
126
  model: 'gpt-4-turbo-preview',
62
127
  messages: [
63
- { role: 'system', content: 'You are a helpful assistant.' },
64
- { role: 'user', content: 'Hello!' },
128
+ { role: 'user', content: 'Explain blockchain' }
65
129
  ],
66
130
  temperature: 0.7,
67
- max_tokens: 500,
131
+ max_tokens: 150
68
132
  });
69
133
 
70
134
  console.log(response.choices[0].message.content);
71
135
  ```
72
136
 
73
- ### Conversation History Management
137
+ ### Using from Browser/Frontend
138
+
139
+ Your frontend apps can call the Pioneer server endpoints without exposing API keys:
74
140
 
75
141
  ```typescript
76
- // Get history
77
- const history = client.getHistory();
142
+ // Using OpenAI client library with Pioneer server as base URL
143
+ import OpenAI from 'openai';
78
144
 
79
- // Clear history (keep system prompt)
80
- client.clearHistory(true);
145
+ const client = new OpenAI({
146
+ apiKey: 'not-needed', // Server handles authentication
147
+ baseURL: 'http://localhost:9001/v1',
148
+ dangerouslyAllowBrowser: true // Only because we're proxying
149
+ });
81
150
 
82
- // Clear everything
83
- client.clearHistory(false);
151
+ const completion = await client.chat.completions.create({
152
+ model: 'gpt-4-turbo-preview',
153
+ messages: [
154
+ { role: 'user', content: 'What is Ethereum?' }
155
+ ]
156
+ });
84
157
 
85
- // Get message count
86
- const count = client.getMessageCount();
158
+ console.log(completion.choices[0].message.content);
87
159
  ```
88
160
 
89
- ## API
90
-
91
- ### InferenceClient
92
-
93
- #### Constructor
161
+ Or using fetch directly:
94
162
 
95
163
  ```typescript
96
- new InferenceClient(config: InferenceConfig)
97
- ```
98
-
99
- **InferenceConfig:**
100
- - `provider`: `'openai' | 'anthropic' | 'ollama' | 'custom'`
101
- - `apiKey?`: API key for the provider
102
- - `baseURL?`: Custom base URL (for OpenAI-compatible endpoints)
103
- - `defaultModel?`: Default model to use
104
- - `timeout?`: Request timeout in milliseconds (default: 60000)
105
-
106
- #### Methods
164
+ const response = await fetch('http://localhost:9001/v1/chat/completions', {
165
+ method: 'POST',
166
+ headers: {
167
+ 'Content-Type': 'application/json'
168
+ },
169
+ body: JSON.stringify({
170
+ model: 'gpt-4-turbo-preview',
171
+ messages: [
172
+ { role: 'user', content: 'What is Ethereum?' }
173
+ ]
174
+ })
175
+ });
107
176
 
108
- - `chat(message: string, options?: Partial<ChatCompletionRequest>): Promise<string>`
109
- - Send a chat message and get a response
177
+ const data = await response.json();
178
+ console.log(data.choices[0].message.content);
179
+ ```
110
180
 
111
- - `chatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse>`
112
- - Full control over chat completion request
181
+ ## System Prompt Injection
113
182
 
114
- - `setSystemPrompt(prompt: string): void`
115
- - Set or update the system prompt
183
+ The service automatically injects a system prompt if:
184
+ 1. A system prompt is configured via `INFERENCE_SYSTEM_PROMPT` or in the config
185
+ 2. The messages array doesn't already contain a system message
116
186
 
117
- - `clearHistory(keepSystemPrompt?: boolean): void`
118
- - Clear conversation history
187
+ This ensures consistent model behavior across all requests without requiring clients to specify the system prompt.
119
188
 
120
- - `getHistory(): Message[]`
121
- - Get conversation history
189
+ ## Security Considerations
122
190
 
123
- - `getMessageCount(): number`
124
- - Get message count (excluding system messages)
191
+ - **Never expose your API keys to the frontend** - always use the server proxy
192
+ - The Pioneer server should be configured with appropriate CORS settings
193
+ - Consider adding authentication to the inference endpoints for production use
194
+ - Rate limiting should be implemented to prevent API abuse
125
195
 
126
- - `isConfigured(): boolean`
127
- - Check if provider is properly configured
196
+ ## API Compatibility
128
197
 
129
- - `getProviderName(): string`
130
- - Get the current provider name
198
+ This module implements the OpenAI Chat Completions API specification, making it compatible with:
199
+ - OpenAI's official client libraries
200
+ - Any tool or library that supports OpenAI-compatible APIs
201
+ - LangChain, LlamaIndex, and other AI frameworks
131
202
 
132
- ## Supported Providers
203
+ ## Development
133
204
 
134
- ### OpenAI (Implemented)
135
- - Native OpenAI API support
136
- - Custom OpenAI-compatible endpoints (like pioneer-server)
205
+ Build the module:
206
+ ```bash
207
+ cd modules/pioneer/pioneer-inference
208
+ bun run build
209
+ ```
137
210
 
138
- ### Coming Soon
139
- - Anthropic (Claude)
140
- - Ollama (local models)
141
- - Custom providers
211
+ Watch for changes:
212
+ ```bash
213
+ bun run build:watch
214
+ ```
142
215
 
143
216
  ## License
144
217
 
@@ -0,0 +1,80 @@
1
+ export type InferenceProvider = 'openai' | 'openrouter' | 'venice';
2
+ export interface InferenceConfig {
3
+ provider: InferenceProvider;
4
+ apiKey: string;
5
+ baseURL?: string;
6
+ systemPrompt?: string;
7
+ defaultModel?: string;
8
+ }
9
+ export interface ChatMessage {
10
+ role: 'system' | 'user' | 'assistant';
11
+ content: string;
12
+ }
13
+ export interface ChatCompletionRequest {
14
+ model: string;
15
+ messages: ChatMessage[];
16
+ temperature?: number;
17
+ max_tokens?: number;
18
+ stream?: boolean;
19
+ [key: string]: any;
20
+ }
21
+ export interface ChatCompletionResponse {
22
+ id: string;
23
+ object: string;
24
+ created: number;
25
+ model: string;
26
+ choices: Array<{
27
+ index: number;
28
+ message: ChatMessage;
29
+ finish_reason: string;
30
+ }>;
31
+ usage: {
32
+ prompt_tokens: number;
33
+ completion_tokens: number;
34
+ total_tokens: number;
35
+ };
36
+ }
37
+ export declare class InferenceService {
38
+ private client;
39
+ private config;
40
+ private systemPrompt?;
41
+ constructor(config: InferenceConfig);
42
+ /**
43
+ * Get the appropriate base URL for the provider
44
+ */
45
+ private getBaseURL;
46
+ /**
47
+ * Get default model for the provider
48
+ */
49
+ private getDefaultModel;
50
+ /**
51
+ * Create a chat completion
52
+ * This is the main proxy method that injects system prompts and protects API keys
53
+ */
54
+ createChatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
55
+ /**
56
+ * Stream chat completion (for real-time responses)
57
+ */
58
+ createStreamingChatCompletion(request: ChatCompletionRequest): Promise<any>;
59
+ /**
60
+ * List available models
61
+ */
62
+ listModels(): Promise<any>;
63
+ /**
64
+ * Get provider information
65
+ */
66
+ getProviderInfo(): {
67
+ provider: InferenceProvider;
68
+ hasSystemPrompt: boolean;
69
+ };
70
+ /**
71
+ * Update system prompt
72
+ */
73
+ setSystemPrompt(prompt: string): void;
74
+ }
75
+ /**
76
+ * Factory function to create inference service from environment variables
77
+ */
78
+ export declare function createInferenceServiceFromEnv(): InferenceService;
79
+ export default InferenceService;
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,WAAW,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,KAAK,EAAE;QACH,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACxB,CAAC;CACL;AAED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,YAAY,CAAC,CAAS;gBAElB,MAAM,EAAE,eAAe;IAiBnC;;OAEG;IACH,OAAO,CAAC,UAAU;IAiBlB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;OAGG;IACG,oBAAoB,CACtB,OAAO,EAAE,qBAAqB,GAC/B,OAAO,CAAC,sBAAsB,CAAC;IAgClC;;OAEG;IACG,6BAA6B,CAC/B,OAAO,EAAE,qBAAqB,GAC/B,OAAO,CAAC,GAAG,CAAC;IAgCf;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;IAYhC;;OAEG;IACH,eAAe,IAAI;QAAE,QAAQ,EAAE,iBAAiB,CAAC;QAAC,eAAe,EAAE,OAAO,CAAA;KAAE;IAO5E;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAGxC;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,gBAAgB,CAoBhE;AAED,eAAe,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /*
3
+ Inference Proxy
4
+
5
+ Goals:
6
+ - Match OpenAI's API structure for compatibility
7
+ - Allow configuring between openai, openrouter, venice.ai
8
+ - All providers follow the OpenAI API format
9
+ - Primary purpose: system prompt injection and API key protection
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.InferenceService = void 0;
16
+ exports.createInferenceServiceFromEnv = createInferenceServiceFromEnv;
17
+ const TAG = ' | pioneer-inference | ';
18
+ const log = require('@pioneer-platform/loggerdog')();
19
+ const openai_1 = __importDefault(require("openai"));
20
+ class InferenceService {
21
+ constructor(config) {
22
+ const tag = TAG + ' | constructor | ';
23
+ this.config = config;
24
+ this.systemPrompt = config.systemPrompt;
25
+ // Get base URL based on provider
26
+ const baseURL = this.getBaseURL();
27
+ log.info(tag, `Initializing ${config.provider} with baseURL: ${baseURL}`);
28
+ // Initialize OpenAI client (works with all OpenAI-compatible APIs)
29
+ this.client = new openai_1.default({
30
+ apiKey: config.apiKey,
31
+ baseURL,
32
+ });
33
+ }
34
+ /**
35
+ * Get the appropriate base URL for the provider
36
+ */
37
+ getBaseURL() {
38
+ if (this.config.baseURL) {
39
+ return this.config.baseURL;
40
+ }
41
+ switch (this.config.provider) {
42
+ case 'openai':
43
+ return undefined; // Use default OpenAI URL
44
+ case 'openrouter':
45
+ return 'https://openrouter.ai/api/v1';
46
+ case 'venice':
47
+ return 'https://api.venice.ai/api/v1';
48
+ default:
49
+ return undefined;
50
+ }
51
+ }
52
+ /**
53
+ * Get default model for the provider
54
+ */
55
+ getDefaultModel() {
56
+ if (this.config.defaultModel) {
57
+ return this.config.defaultModel;
58
+ }
59
+ switch (this.config.provider) {
60
+ case 'openai':
61
+ return 'gpt-4-turbo-preview';
62
+ case 'openrouter':
63
+ return 'anthropic/claude-3-opus';
64
+ case 'venice':
65
+ return 'llama-3.1-405b';
66
+ default:
67
+ return 'gpt-4-turbo-preview';
68
+ }
69
+ }
70
+ /**
71
+ * Create a chat completion
72
+ * This is the main proxy method that injects system prompts and protects API keys
73
+ */
74
+ async createChatCompletion(request) {
75
+ const tag = TAG + ' | createChatCompletion | ';
76
+ try {
77
+ // Inject system prompt if configured and not already present
78
+ const messages = [...request.messages];
79
+ if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
80
+ messages.unshift({
81
+ role: 'system',
82
+ content: this.systemPrompt,
83
+ });
84
+ }
85
+ // Use configured default model if not specified
86
+ const model = request.model || this.getDefaultModel();
87
+ log.info(tag, `Creating completion with model: ${model}, messages: ${messages.length}`);
88
+ // Make the API call
89
+ const completion = await this.client.chat.completions.create({
90
+ ...request,
91
+ model,
92
+ messages,
93
+ });
94
+ return completion;
95
+ }
96
+ catch (error) {
97
+ log.error(tag, 'Error creating chat completion:', error);
98
+ throw error;
99
+ }
100
+ }
101
+ /**
102
+ * Stream chat completion (for real-time responses)
103
+ */
104
+ async createStreamingChatCompletion(request) {
105
+ const tag = TAG + ' | createStreamingChatCompletion | ';
106
+ try {
107
+ // Inject system prompt if configured
108
+ const messages = [...request.messages];
109
+ if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
110
+ messages.unshift({
111
+ role: 'system',
112
+ content: this.systemPrompt,
113
+ });
114
+ }
115
+ const model = request.model || this.getDefaultModel();
116
+ log.info(tag, `Creating streaming completion with model: ${model}`);
117
+ // Make streaming API call
118
+ const stream = await this.client.chat.completions.create({
119
+ ...request,
120
+ model,
121
+ messages,
122
+ stream: true,
123
+ });
124
+ return stream;
125
+ }
126
+ catch (error) {
127
+ log.error(tag, 'Error creating streaming chat completion:', error);
128
+ throw error;
129
+ }
130
+ }
131
+ /**
132
+ * List available models
133
+ */
134
+ async listModels() {
135
+ const tag = TAG + ' | listModels | ';
136
+ try {
137
+ const models = await this.client.models.list();
138
+ return models;
139
+ }
140
+ catch (error) {
141
+ log.error(tag, 'Error listing models:', error);
142
+ throw error;
143
+ }
144
+ }
145
+ /**
146
+ * Get provider information
147
+ */
148
+ getProviderInfo() {
149
+ return {
150
+ provider: this.config.provider,
151
+ hasSystemPrompt: !!this.systemPrompt,
152
+ };
153
+ }
154
+ /**
155
+ * Update system prompt
156
+ */
157
+ setSystemPrompt(prompt) {
158
+ this.systemPrompt = prompt;
159
+ }
160
+ }
161
+ exports.InferenceService = InferenceService;
162
+ /**
163
+ * Factory function to create inference service from environment variables
164
+ */
165
+ function createInferenceServiceFromEnv() {
166
+ const tag = TAG + ' | createInferenceServiceFromEnv | ';
167
+ const provider = (process.env.INFERENCE_PROVIDER || 'openai');
168
+ const apiKey = process.env.INFERENCE_API_KEY || process.env.OPENAI_API_KEY || '';
169
+ const baseURL = process.env.INFERENCE_BASE_URL;
170
+ const systemPrompt = process.env.INFERENCE_SYSTEM_PROMPT;
171
+ const defaultModel = process.env.INFERENCE_DEFAULT_MODEL;
172
+ if (!apiKey) {
173
+ log.warn(tag, 'No API key found in environment variables');
174
+ }
175
+ return new InferenceService({
176
+ provider,
177
+ apiKey,
178
+ baseURL,
179
+ systemPrompt,
180
+ defaultModel,
181
+ });
182
+ }
183
+ exports.default = InferenceService;
184
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,36 +1,29 @@
1
1
  {
2
2
  "name": "@pioneer-platform/pioneer-inference",
3
- "version": "1.0.0",
4
- "description": "LLM inference abstraction layer for Pioneer platform",
5
- "main": "./lib/index.js",
6
- "types": "./lib/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./lib/index.d.ts",
10
- "default": "./lib/index.js"
11
- }
12
- },
3
+ "version": "1.0.1",
4
+ "description": "OpenAI-compatible inference proxy for Pioneer platform",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
13
7
  "scripts": {
14
- "build": "tsc -p .",
15
- "build:watch": "tsc -p . --watch",
16
- "test": "echo \"Error: no test specified\" && exit 1",
17
- "prepublish": "npm run build"
8
+ "build": "tsc",
9
+ "build:watch": "tsc --watch",
10
+ "clean": "rm -rf dist node_modules"
18
11
  },
19
12
  "keywords": [
20
- "ai",
21
- "llm",
22
- "openai",
13
+ "pioneer",
23
14
  "inference",
24
- "pioneer"
15
+ "openai",
16
+ "ai",
17
+ "llm"
25
18
  ],
26
- "author": "Pioneer Platform",
27
- "license": "MIT",
19
+ "author": "",
20
+ "license": "ISC",
28
21
  "dependencies": {
22
+ "@pioneer-platform/loggerdog": "^8.0.0",
29
23
  "openai": "^4.26.0"
30
24
  },
31
- "peerDependencies": {},
32
25
  "devDependencies": {
33
- "@types/node": "^20.11.16",
34
- "typescript": "^5.3.3"
26
+ "@types/node": "^22.14.1",
27
+ "typescript": "^5.8.3"
35
28
  }
36
29
  }
package/src/index.ts CHANGED
@@ -1,30 +1,252 @@
1
+ /*
2
+ Inference Proxy
3
+
4
+ Goals:
5
+ - Match OpenAI's API structure for compatibility
6
+ - Allow configuring between openai, openrouter, venice.ai
7
+ - All providers follow the OpenAI API format
8
+ - Primary purpose: system prompt injection and API key protection
9
+ */
10
+
11
+ const TAG = ' | pioneer-inference | ';
12
+ const log = require('@pioneer-platform/loggerdog')();
13
+
14
+ import OpenAI from 'openai';
15
+
16
+ export type InferenceProvider = 'openai' | 'openrouter' | 'venice';
17
+
18
+ export interface InferenceConfig {
19
+ provider: InferenceProvider;
20
+ apiKey: string;
21
+ baseURL?: string;
22
+ systemPrompt?: string;
23
+ defaultModel?: string;
24
+ }
25
+
26
+ export interface ChatMessage {
27
+ role: 'system' | 'user' | 'assistant';
28
+ content: string;
29
+ }
30
+
31
+ export interface ChatCompletionRequest {
32
+ model: string;
33
+ messages: ChatMessage[];
34
+ temperature?: number;
35
+ max_tokens?: number;
36
+ stream?: boolean;
37
+ [key: string]: any;
38
+ }
39
+
40
+ export interface ChatCompletionResponse {
41
+ id: string;
42
+ object: string;
43
+ created: number;
44
+ model: string;
45
+ choices: Array<{
46
+ index: number;
47
+ message: ChatMessage;
48
+ finish_reason: string;
49
+ }>;
50
+ usage: {
51
+ prompt_tokens: number;
52
+ completion_tokens: number;
53
+ total_tokens: number;
54
+ };
55
+ }
56
+
57
+ export class InferenceService {
58
+ private client: OpenAI;
59
+ private config: InferenceConfig;
60
+ private systemPrompt?: string;
61
+
62
+ constructor(config: InferenceConfig) {
63
+ const tag = TAG + ' | constructor | ';
64
+ this.config = config;
65
+ this.systemPrompt = config.systemPrompt;
66
+
67
+ // Get base URL based on provider
68
+ const baseURL = this.getBaseURL();
69
+
70
+ log.info(tag, `Initializing ${config.provider} with baseURL: ${baseURL}`);
71
+
72
+ // Initialize OpenAI client (works with all OpenAI-compatible APIs)
73
+ this.client = new OpenAI({
74
+ apiKey: config.apiKey,
75
+ baseURL,
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Get the appropriate base URL for the provider
81
+ */
82
+ private getBaseURL(): string | undefined {
83
+ if (this.config.baseURL) {
84
+ return this.config.baseURL;
85
+ }
86
+
87
+ switch (this.config.provider) {
88
+ case 'openai':
89
+ return undefined; // Use default OpenAI URL
90
+ case 'openrouter':
91
+ return 'https://openrouter.ai/api/v1';
92
+ case 'venice':
93
+ return 'https://api.venice.ai/api/v1';
94
+ default:
95
+ return undefined;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Get default model for the provider
101
+ */
102
+ private getDefaultModel(): string {
103
+ if (this.config.defaultModel) {
104
+ return this.config.defaultModel;
105
+ }
106
+
107
+ switch (this.config.provider) {
108
+ case 'openai':
109
+ return 'gpt-4-turbo-preview';
110
+ case 'openrouter':
111
+ return 'anthropic/claude-3-opus';
112
+ case 'venice':
113
+ return 'llama-3.1-405b';
114
+ default:
115
+ return 'gpt-4-turbo-preview';
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Create a chat completion
121
+ * This is the main proxy method that injects system prompts and protects API keys
122
+ */
123
+ async createChatCompletion(
124
+ request: ChatCompletionRequest
125
+ ): Promise<ChatCompletionResponse> {
126
+ const tag = TAG + ' | createChatCompletion | ';
127
+
128
+ try {
129
+ // Inject system prompt if configured and not already present
130
+ const messages = [...request.messages];
131
+ if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
132
+ messages.unshift({
133
+ role: 'system',
134
+ content: this.systemPrompt,
135
+ });
136
+ }
137
+
138
+ // Use configured default model if not specified
139
+ const model = request.model || this.getDefaultModel();
140
+
141
+ log.info(tag, `Creating completion with model: ${model}, messages: ${messages.length}`);
142
+
143
+ // Make the API call
144
+ const completion = await this.client.chat.completions.create({
145
+ ...request,
146
+ model,
147
+ messages,
148
+ });
149
+
150
+ return completion as ChatCompletionResponse;
151
+ } catch (error: any) {
152
+ log.error(tag, 'Error creating chat completion:', error);
153
+ throw error;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Stream chat completion (for real-time responses)
159
+ */
160
+ async createStreamingChatCompletion(
161
+ request: ChatCompletionRequest
162
+ ): Promise<any> {
163
+ const tag = TAG + ' | createStreamingChatCompletion | ';
164
+
165
+ try {
166
+ // Inject system prompt if configured
167
+ const messages = [...request.messages];
168
+ if (this.systemPrompt && !messages.some(m => m.role === 'system')) {
169
+ messages.unshift({
170
+ role: 'system',
171
+ content: this.systemPrompt,
172
+ });
173
+ }
174
+
175
+ const model = request.model || this.getDefaultModel();
176
+
177
+ log.info(tag, `Creating streaming completion with model: ${model}`);
178
+
179
+ // Make streaming API call
180
+ const stream = await this.client.chat.completions.create({
181
+ ...request,
182
+ model,
183
+ messages,
184
+ stream: true,
185
+ });
186
+
187
+ return stream;
188
+ } catch (error: any) {
189
+ log.error(tag, 'Error creating streaming chat completion:', error);
190
+ throw error;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * List available models
196
+ */
197
+ async listModels(): Promise<any> {
198
+ const tag = TAG + ' | listModels | ';
199
+
200
+ try {
201
+ const models = await this.client.models.list();
202
+ return models;
203
+ } catch (error: any) {
204
+ log.error(tag, 'Error listing models:', error);
205
+ throw error;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Get provider information
211
+ */
212
+ getProviderInfo(): { provider: InferenceProvider; hasSystemPrompt: boolean } {
213
+ return {
214
+ provider: this.config.provider,
215
+ hasSystemPrompt: !!this.systemPrompt,
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Update system prompt
221
+ */
222
+ setSystemPrompt(prompt: string): void {
223
+ this.systemPrompt = prompt;
224
+ }
225
+ }
226
+
1
227
  /**
2
- * Pioneer Inference
3
- *
4
- * LLM inference abstraction layer for Pioneer platform
5
- *
6
- * @example
7
- * ```typescript
8
- * import { InferenceClient } from '@pioneer-platform/pioneer-inference';
9
- *
10
- * const client = new InferenceClient({
11
- * provider: 'openai',
12
- * apiKey: process.env.OPENAI_API_KEY,
13
- * });
14
- *
15
- * client.setSystemPrompt('You are a helpful assistant.');
16
- * const response = await client.chat('Hello!');
17
- * console.log(response);
18
- * ```
228
+ * Factory function to create inference service from environment variables
19
229
  */
230
+ export function createInferenceServiceFromEnv(): InferenceService {
231
+ const tag = TAG + ' | createInferenceServiceFromEnv | ';
232
+
233
+ const provider = (process.env.INFERENCE_PROVIDER || 'openai') as InferenceProvider;
234
+ const apiKey = process.env.INFERENCE_API_KEY || process.env.OPENAI_API_KEY || '';
235
+ const baseURL = process.env.INFERENCE_BASE_URL;
236
+ const systemPrompt = process.env.INFERENCE_SYSTEM_PROMPT;
237
+ const defaultModel = process.env.INFERENCE_DEFAULT_MODEL;
238
+
239
+ if (!apiKey) {
240
+ log.warn(tag, 'No API key found in environment variables');
241
+ }
20
242
 
21
- export { InferenceClient } from './inference';
22
- export { OpenAIProvider } from './providers/openai';
243
+ return new InferenceService({
244
+ provider,
245
+ apiKey,
246
+ baseURL,
247
+ systemPrompt,
248
+ defaultModel,
249
+ });
250
+ }
23
251
 
24
- export type {
25
- Message,
26
- ChatCompletionRequest,
27
- ChatCompletionResponse,
28
- InferenceProvider,
29
- InferenceConfig,
30
- } from './types';
252
+ export default InferenceService;
package/tsconfig.json CHANGED
@@ -3,16 +3,18 @@
3
3
  "target": "ES2020",
4
4
  "module": "commonjs",
5
5
  "lib": ["ES2020"],
6
- "declaration": true,
7
- "outDir": "./lib",
6
+ "outDir": "./dist",
8
7
  "rootDir": "./src",
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
9
11
  "strict": true,
10
12
  "esModuleInterop": true,
11
13
  "skipLibCheck": true,
12
14
  "forceConsistentCasingInFileNames": true,
13
- "moduleResolution": "node",
14
- "resolveJsonModule": true
15
+ "resolveJsonModule": true,
16
+ "moduleResolution": "node"
15
17
  },
16
18
  "include": ["src/**/*"],
17
- "exclude": ["node_modules", "lib", "__tests__"]
19
+ "exclude": ["node_modules", "dist"]
18
20
  }
package/src/inference.ts DELETED
@@ -1,138 +0,0 @@
1
- /**
2
- * Main Inference Client
3
- *
4
- * Provides a unified interface for LLM inference across multiple providers
5
- */
6
-
7
- import type {
8
- InferenceConfig,
9
- InferenceProvider,
10
- ChatCompletionRequest,
11
- ChatCompletionResponse,
12
- Message,
13
- } from './types';
14
- import { OpenAIProvider } from './providers/openai';
15
-
16
- export class InferenceClient {
17
- private provider: InferenceProvider;
18
- private conversationHistory: Message[] = [];
19
-
20
- constructor(config: InferenceConfig) {
21
- this.provider = this.createProvider(config);
22
- }
23
-
24
- private createProvider(config: InferenceConfig): InferenceProvider {
25
- switch (config.provider) {
26
- case 'openai':
27
- if (!config.apiKey) {
28
- throw new Error('OpenAI API key is required');
29
- }
30
- return new OpenAIProvider({
31
- apiKey: config.apiKey,
32
- baseURL: config.baseURL,
33
- timeout: config.timeout,
34
- defaultModel: config.defaultModel,
35
- });
36
-
37
- case 'anthropic':
38
- throw new Error('Anthropic provider not yet implemented');
39
-
40
- case 'ollama':
41
- throw new Error('Ollama provider not yet implemented');
42
-
43
- case 'custom':
44
- throw new Error('Custom provider requires implementation');
45
-
46
- default:
47
- throw new Error(`Unknown provider: ${config.provider}`);
48
- }
49
- }
50
-
51
- /**
52
- * Send a chat message
53
- */
54
- async chat(message: string, options?: Partial<ChatCompletionRequest>): Promise<string> {
55
- // Add user message to history
56
- this.conversationHistory.push({
57
- role: 'user',
58
- content: message,
59
- });
60
-
61
- const request: ChatCompletionRequest = {
62
- model: options?.model || 'gpt-4-turbo-preview',
63
- messages: this.conversationHistory,
64
- ...options,
65
- };
66
-
67
- const response = await this.provider.chat(request);
68
- const assistantMessage = response.choices[0]?.message?.content || '';
69
-
70
- // Add assistant response to history
71
- this.conversationHistory.push({
72
- role: 'assistant',
73
- content: assistantMessage,
74
- });
75
-
76
- return assistantMessage;
77
- }
78
-
79
- /**
80
- * Send a chat completion request with full control
81
- */
82
- async chatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse> {
83
- return this.provider.chat(request);
84
- }
85
-
86
- /**
87
- * Set system prompt
88
- */
89
- setSystemPrompt(prompt: string): void {
90
- // Remove existing system message if any
91
- this.conversationHistory = this.conversationHistory.filter(m => m.role !== 'system');
92
-
93
- // Add new system message at the beginning
94
- this.conversationHistory.unshift({
95
- role: 'system',
96
- content: prompt,
97
- });
98
- }
99
-
100
- /**
101
- * Clear conversation history (optionally keep system prompt)
102
- */
103
- clearHistory(keepSystemPrompt: boolean = true): void {
104
- if (keepSystemPrompt) {
105
- this.conversationHistory = this.conversationHistory.filter(m => m.role === 'system');
106
- } else {
107
- this.conversationHistory = [];
108
- }
109
- }
110
-
111
- /**
112
- * Get conversation history
113
- */
114
- getHistory(): Message[] {
115
- return [...this.conversationHistory];
116
- }
117
-
118
- /**
119
- * Get message count (excluding system messages)
120
- */
121
- getMessageCount(): number {
122
- return this.conversationHistory.filter(m => m.role !== 'system').length;
123
- }
124
-
125
- /**
126
- * Check if provider is configured
127
- */
128
- isConfigured(): boolean {
129
- return this.provider.isConfigured();
130
- }
131
-
132
- /**
133
- * Get provider name
134
- */
135
- getProviderName(): string {
136
- return this.provider.name;
137
- }
138
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * OpenAI Provider Implementation
3
- */
4
-
5
- import OpenAI from 'openai';
6
- import type {
7
- InferenceProvider,
8
- ChatCompletionRequest,
9
- ChatCompletionResponse,
10
- } from '../types';
11
-
12
- export interface OpenAIConfig {
13
- apiKey: string;
14
- baseURL?: string;
15
- timeout?: number;
16
- defaultModel?: string;
17
- }
18
-
19
- export class OpenAIProvider implements InferenceProvider {
20
- public readonly name = 'openai';
21
- private client: OpenAI;
22
- private config: OpenAIConfig;
23
-
24
- constructor(config: OpenAIConfig) {
25
- this.config = config;
26
- this.client = new OpenAI({
27
- apiKey: config.apiKey,
28
- baseURL: config.baseURL,
29
- timeout: config.timeout || 60000,
30
- });
31
- }
32
-
33
- async chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse> {
34
- try {
35
- // Forward ALL parameters from request to OpenAI
36
- // This includes tools, tool_choice, and any other OpenAI-specific params
37
- const { model, messages, ...extraParams } = request;
38
-
39
- const completion = await this.client.chat.completions.create({
40
- model: model || this.config.defaultModel || 'gpt-4-turbo-preview',
41
- messages: messages as any,
42
- ...extraParams, // Forward all extra parameters (tools, tool_choice, etc.)
43
- });
44
-
45
- // Convert OpenAI response to our standard format
46
- return completion as ChatCompletionResponse;
47
- } catch (error) {
48
- if (error instanceof OpenAI.APIError) {
49
- throw new Error(`OpenAI API Error: ${error.message}`);
50
- }
51
- throw error;
52
- }
53
- }
54
-
55
- isConfigured(): boolean {
56
- return !!this.config.apiKey;
57
- }
58
-
59
- /**
60
- * Update the base URL (useful for pointing to different endpoints)
61
- */
62
- setBaseURL(baseURL: string): void {
63
- this.client = new OpenAI({
64
- apiKey: this.config.apiKey,
65
- baseURL,
66
- timeout: this.config.timeout,
67
- });
68
- }
69
- }
package/src/types.ts DELETED
@@ -1,55 +0,0 @@
1
- /**
2
- * Common types for LLM inference
3
- */
4
-
5
- export interface Message {
6
- role: 'system' | 'user' | 'assistant' | 'tool';
7
- content: string | null;
8
- tool_calls?: any[];
9
- tool_call_id?: string;
10
- name?: string;
11
- }
12
-
13
- export interface ChatCompletionRequest {
14
- model: string;
15
- messages: Message[];
16
- temperature?: number;
17
- max_tokens?: number;
18
- stream?: boolean;
19
- [key: string]: any;
20
- }
21
-
22
- export interface ChatCompletionResponse {
23
- id: string;
24
- object: string;
25
- created: number;
26
- model: string;
27
- choices: Array<{
28
- index: number;
29
- message: {
30
- role: string;
31
- content: string | null;
32
- tool_calls?: any[];
33
- };
34
- finish_reason: string;
35
- }>;
36
- usage?: {
37
- prompt_tokens: number;
38
- completion_tokens: number;
39
- total_tokens: number;
40
- };
41
- }
42
-
43
- export interface InferenceProvider {
44
- name: string;
45
- chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
46
- isConfigured(): boolean;
47
- }
48
-
49
- export interface InferenceConfig {
50
- provider: 'openai' | 'anthropic' | 'ollama' | 'custom';
51
- apiKey?: string;
52
- baseURL?: string;
53
- defaultModel?: string;
54
- timeout?: number;
55
- }