@pioneer-platform/pioneer-inference 1.0.0
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.
- package/README.md +145 -0
- package/package.json +36 -0
- package/src/index.ts +30 -0
- package/src/inference.ts +138 -0
- package/src/providers/openai.ts +69 -0
- package/src/types.ts +55 -0
- package/tsconfig.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# @pioneer-platform/pioneer-inference
|
|
2
|
+
|
|
3
|
+
LLM inference abstraction layer for the Pioneer platform. Provides a unified interface for working with multiple LLM providers (OpenAI, Anthropic, Ollama, etc.).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pioneer-platform/pioneer-inference
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { InferenceClient } from '@pioneer-platform/pioneer-inference';
|
|
17
|
+
|
|
18
|
+
const client = new InferenceClient({
|
|
19
|
+
provider: 'openai',
|
|
20
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Set system prompt
|
|
24
|
+
client.setSystemPrompt('You are a helpful coding assistant.');
|
|
25
|
+
|
|
26
|
+
// Send a message
|
|
27
|
+
const response = await client.chat('Help me write a function');
|
|
28
|
+
console.log(response);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Point to Custom Endpoint
|
|
32
|
+
|
|
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
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Using with Pioneer Server
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { InferenceClient } from '@pioneer-platform/pioneer-inference';
|
|
46
|
+
|
|
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
|
+
});
|
|
53
|
+
|
|
54
|
+
const response = await client.chat('What can you help me with?');
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Full Control with Chat Completions
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const response = await client.chatCompletion({
|
|
61
|
+
model: 'gpt-4-turbo-preview',
|
|
62
|
+
messages: [
|
|
63
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
64
|
+
{ role: 'user', content: 'Hello!' },
|
|
65
|
+
],
|
|
66
|
+
temperature: 0.7,
|
|
67
|
+
max_tokens: 500,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
console.log(response.choices[0].message.content);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Conversation History Management
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Get history
|
|
77
|
+
const history = client.getHistory();
|
|
78
|
+
|
|
79
|
+
// Clear history (keep system prompt)
|
|
80
|
+
client.clearHistory(true);
|
|
81
|
+
|
|
82
|
+
// Clear everything
|
|
83
|
+
client.clearHistory(false);
|
|
84
|
+
|
|
85
|
+
// Get message count
|
|
86
|
+
const count = client.getMessageCount();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
### InferenceClient
|
|
92
|
+
|
|
93
|
+
#### Constructor
|
|
94
|
+
|
|
95
|
+
```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
|
|
107
|
+
|
|
108
|
+
- `chat(message: string, options?: Partial<ChatCompletionRequest>): Promise<string>`
|
|
109
|
+
- Send a chat message and get a response
|
|
110
|
+
|
|
111
|
+
- `chatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse>`
|
|
112
|
+
- Full control over chat completion request
|
|
113
|
+
|
|
114
|
+
- `setSystemPrompt(prompt: string): void`
|
|
115
|
+
- Set or update the system prompt
|
|
116
|
+
|
|
117
|
+
- `clearHistory(keepSystemPrompt?: boolean): void`
|
|
118
|
+
- Clear conversation history
|
|
119
|
+
|
|
120
|
+
- `getHistory(): Message[]`
|
|
121
|
+
- Get conversation history
|
|
122
|
+
|
|
123
|
+
- `getMessageCount(): number`
|
|
124
|
+
- Get message count (excluding system messages)
|
|
125
|
+
|
|
126
|
+
- `isConfigured(): boolean`
|
|
127
|
+
- Check if provider is properly configured
|
|
128
|
+
|
|
129
|
+
- `getProviderName(): string`
|
|
130
|
+
- Get the current provider name
|
|
131
|
+
|
|
132
|
+
## Supported Providers
|
|
133
|
+
|
|
134
|
+
### OpenAI (Implemented)
|
|
135
|
+
- Native OpenAI API support
|
|
136
|
+
- Custom OpenAI-compatible endpoints (like pioneer-server)
|
|
137
|
+
|
|
138
|
+
### Coming Soon
|
|
139
|
+
- Anthropic (Claude)
|
|
140
|
+
- Ollama (local models)
|
|
141
|
+
- Custom providers
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
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
|
+
},
|
|
13
|
+
"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"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"ai",
|
|
21
|
+
"llm",
|
|
22
|
+
"openai",
|
|
23
|
+
"inference",
|
|
24
|
+
"pioneer"
|
|
25
|
+
],
|
|
26
|
+
"author": "Pioneer Platform",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"openai": "^4.26.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.11.16",
|
|
34
|
+
"typescript": "^5.3.3"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
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
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export { InferenceClient } from './inference';
|
|
22
|
+
export { OpenAIProvider } from './providers/openai';
|
|
23
|
+
|
|
24
|
+
export type {
|
|
25
|
+
Message,
|
|
26
|
+
ChatCompletionRequest,
|
|
27
|
+
ChatCompletionResponse,
|
|
28
|
+
InferenceProvider,
|
|
29
|
+
InferenceConfig,
|
|
30
|
+
} from './types';
|
package/src/inference.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./lib",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"moduleResolution": "node",
|
|
14
|
+
"resolveJsonModule": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "lib", "__tests__"]
|
|
18
|
+
}
|