symmetry-cli 1.0.2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- package/__test__/cli.test.ts +4 -3
- package/dist/provider.js +8 -4
- package/install.ps1 +6 -36
- package/package.json +1 -1
- package/readme.md +54 -85
- package/src/provider.ts +17 -8
- package/src/types.ts +2 -1
package/__test__/cli.test.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { SymmetryProvider } from "../src/provider";
|
2
2
|
import yaml from "js-yaml";
|
3
3
|
|
4
4
|
jest.mock("hyperswarm", () => {
|
@@ -33,7 +33,7 @@ jest.mock("js-yaml", () => ({
|
|
33
33
|
|
34
34
|
|
35
35
|
describe("Symmetry", () => {
|
36
|
-
let writer:
|
36
|
+
let writer: SymmetryProvider;
|
37
37
|
const mockConfig = {
|
38
38
|
path: "/test/path",
|
39
39
|
temperature: 1,
|
@@ -47,12 +47,13 @@ describe("Symmetry", () => {
|
|
47
47
|
name: "test",
|
48
48
|
public: true,
|
49
49
|
serverKey: "test-server-key",
|
50
|
+
systemMessage: "test-system-message",
|
50
51
|
};
|
51
52
|
|
52
53
|
beforeEach(() => {
|
53
54
|
jest.clearAllMocks();
|
54
55
|
(yaml.load as jest.Mock).mockReturnValue(mockConfig);
|
55
|
-
writer = new
|
56
|
+
writer = new SymmetryProvider("mock-config.yaml");
|
56
57
|
});
|
57
58
|
|
58
59
|
test("init method sets up the writer correctly", async () => {
|
package/dist/provider.js
CHANGED
@@ -149,7 +149,14 @@ class SymmetryProvider {
|
|
149
149
|
}
|
150
150
|
async handleInferenceRequest(data, peer) {
|
151
151
|
const emitterKey = data.data.key;
|
152
|
+
const messages = data === null || data === void 0 ? void 0 : data.data.messages;
|
152
153
|
const req = this.buildStreamRequest(data === null || data === void 0 ? void 0 : data.data.messages);
|
154
|
+
if (messages.length === 2) {
|
155
|
+
messages.unshift({
|
156
|
+
role: "system",
|
157
|
+
content: this._config.get("systemMessage"),
|
158
|
+
});
|
159
|
+
}
|
153
160
|
if (!req)
|
154
161
|
return;
|
155
162
|
const { requestOptions, requestBody } = req;
|
@@ -192,10 +199,7 @@ class SymmetryProvider {
|
|
192
199
|
});
|
193
200
|
await Promise.resolve(peerPipeline);
|
194
201
|
peer.write((0, utils_1.createMessage)(constants_1.serverMessageKeys.inferenceEnded, data === null || data === void 0 ? void 0 : data.data.key));
|
195
|
-
|
196
|
-
data.data.key === constants_1.serverMessageKeys.inference) {
|
197
|
-
this.saveCompletion(completion, peer, data.data.messages);
|
198
|
-
}
|
202
|
+
this.saveCompletion(completion, peer, data.data.messages);
|
199
203
|
}
|
200
204
|
catch (error) {
|
201
205
|
let errorMessage = "An error occurred during inference";
|
package/install.ps1
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
+
# Symmetry CLI Install Script for Windows
|
1
2
|
$ErrorActionPreference = "Stop"
|
2
3
|
|
3
|
-
# Colors for output
|
4
4
|
$RED = "`e[31m"
|
5
5
|
$GREEN = "`e[32m"
|
6
6
|
$YELLOW = "`e[33m"
|
@@ -10,48 +10,19 @@ function Print-Color($color, $message) {
|
|
10
10
|
Write-Host "$color$message$NC"
|
11
11
|
}
|
12
12
|
|
13
|
-
# Check if npm is installed
|
14
13
|
if (!(Get-Command npm -ErrorAction SilentlyContinue)) {
|
15
14
|
Print-Color $RED "Error: npm is not installed. Please install Node.js and npm first."
|
16
15
|
exit 1
|
17
16
|
}
|
18
17
|
|
19
|
-
# Install symmetry-cli globally
|
20
18
|
Print-Color $YELLOW "Installing symmetry-cli globally..."
|
21
|
-
|
22
|
-
npm install -g symmetry-cli
|
19
|
+
if (npm install -g .) {
|
23
20
|
Print-Color $GREEN "symmetry-cli installed successfully!"
|
24
|
-
}
|
25
|
-
catch {
|
21
|
+
} else {
|
26
22
|
Print-Color $RED "Failed to install symmetry-cli. Please check your npm configuration and try again."
|
27
23
|
exit 1
|
28
24
|
}
|
29
25
|
|
30
|
-
# Prompt for API provider
|
31
|
-
Print-Color $YELLOW "Please select an API provider:"
|
32
|
-
$providers = @{
|
33
|
-
1 = @{name = "LiteLLM"; value = "litellm"}
|
34
|
-
2 = @{name = "LlamaCpp"; value = "llamacpp"}
|
35
|
-
3 = @{name = "LMStudio"; value = "lmstudio"}
|
36
|
-
4 = @{name = "Ollama"; value = "ollama"}
|
37
|
-
5 = @{name = "Oobabooga"; value = "oobabooga"}
|
38
|
-
6 = @{name = "OpenWebUI"; value = "openwebui"}
|
39
|
-
}
|
40
|
-
|
41
|
-
$providers.GetEnumerator() | ForEach-Object {
|
42
|
-
Write-Host "$($_.Key): $($_.Value.name)"
|
43
|
-
}
|
44
|
-
|
45
|
-
do {
|
46
|
-
$selection = Read-Host "Enter the number of your choice"
|
47
|
-
$api_provider = $providers[$selection].value
|
48
|
-
} while (-not $api_provider)
|
49
|
-
|
50
|
-
# Prompt for model name
|
51
|
-
Print-Color $YELLOW "Please enter the model name you want to use:"
|
52
|
-
$model_name = Read-Host
|
53
|
-
|
54
|
-
# Create config directory and provider.yaml file
|
55
26
|
$config_dir = "$env:USERPROFILE\.config\symmetry"
|
56
27
|
$provider_yaml = "$config_dir\provider.yaml"
|
57
28
|
|
@@ -66,18 +37,17 @@ apiKey:
|
|
66
37
|
apiPath: /v1/chat/completions
|
67
38
|
apiPort: 11434
|
68
39
|
apiProtocol: http
|
69
|
-
apiProvider:
|
40
|
+
apiProvider: ollama
|
70
41
|
dataCollectionEnabled: true
|
71
42
|
maxConnections: 10
|
72
|
-
modelName:
|
43
|
+
modelName: llama3.1:latest
|
73
44
|
name: $env:USERNAME
|
74
45
|
path: $config_dir
|
75
46
|
public: true
|
76
47
|
serverKey: 4b4a9cc325d134dee6679e9407420023531fd7e96c563f6c5d00fd5549b77435
|
77
48
|
"@ | Set-Content $provider_yaml
|
78
49
|
Print-Color $GREEN "provider.yaml created successfully at $provider_yaml"
|
79
|
-
}
|
80
|
-
else {
|
50
|
+
} else {
|
81
51
|
Print-Color $YELLOW "provider.yaml already exists at $provider_yaml"
|
82
52
|
}
|
83
53
|
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -1,63 +1,66 @@
|
|
1
|
-
#
|
1
|
+
# Symmetry
|
2
2
|
|
3
|
-
|
3
|
+
Use this repository to become an inference provider on the Symmetry network.
|
4
|
+
|
5
|
+
Symmetry is a decentralized peer-to-peer network tool that allows users to share computational resources for AI inference. It enables users to connect directly and securely with each other, offering or seeking computational power for various AI tasks.
|
4
6
|
|
5
7
|
## Features
|
6
8
|
|
7
|
-
-
|
8
|
-
-
|
9
|
-
-
|
10
|
-
-
|
9
|
+
- Decentralized peer-to-peer network
|
10
|
+
- YAML-based configuration
|
11
|
+
- Privacy options
|
12
|
+
- Optional data collection for providers
|
13
|
+
- Compatible with various AI inference providers
|
11
14
|
|
12
15
|
## Installation
|
13
16
|
|
14
|
-
To
|
17
|
+
To install Symmetry, use the following commands:
|
15
18
|
|
16
|
-
Linux and
|
17
|
-
```
|
19
|
+
For Linux and macOS:
|
20
|
+
```bash
|
18
21
|
curl -fsSL https://raw.githubusercontent.com/twinnydotdev/symmetry/master/install.sh | sh
|
19
22
|
```
|
20
23
|
|
21
|
-
Windows
|
22
|
-
```
|
24
|
+
For Windows:
|
25
|
+
```powershell
|
23
26
|
iwr -useb https://raw.githubusercontent.com/twinnydotdev/symmetry/master/install.ps1 | iex
|
24
27
|
```
|
25
28
|
|
26
29
|
## Usage
|
27
30
|
|
28
|
-
To
|
31
|
+
To start Symmetry, run:
|
29
32
|
|
30
|
-
```
|
33
|
+
```bash
|
31
34
|
symmetry-cli
|
32
35
|
```
|
33
36
|
|
34
|
-
Symmetry
|
37
|
+
By default, Symmetry looks for its configuration file at `~/.config/symmetry/provider.yaml`. To use a different configuration file, use:
|
35
38
|
|
36
|
-
```
|
37
|
-
symmetry -c /path/to/your/
|
39
|
+
```bash
|
40
|
+
symmetry-cli -c /path/to/your/provider.yaml
|
38
41
|
```
|
39
42
|
|
40
43
|
## Configuration
|
41
44
|
|
42
|
-
|
45
|
+
Here's an example `provider.yaml` configuration:
|
43
46
|
|
44
47
|
```yaml
|
45
|
-
apiHostname: localhost
|
46
|
-
apiKey:
|
47
|
-
apiPath: /v1/chat/completions
|
48
|
-
apiPort: 11434
|
49
|
-
apiProtocol: http
|
50
|
-
apiProvider: ollama
|
51
|
-
dataCollectionEnabled:
|
52
|
-
maxConnections: 10
|
53
|
-
modelName: llama3:
|
54
|
-
name: # Your
|
55
|
-
path: /home/
|
56
|
-
public: true
|
57
|
-
serverKey: 4b4a9cc325d134dee6679e9407420023531fd7e96c563f6c5d00fd5549b77435
|
48
|
+
apiHostname: localhost # The hostname of the API server.
|
49
|
+
apiKey: # The API key for authentication.
|
50
|
+
apiPath: /v1/chat/completions # The endpoint path for chat completions.
|
51
|
+
apiPort: 11434 # The port number on which the API server is listening.
|
52
|
+
apiProtocol: http # The protocol used to communicate with the API server.
|
53
|
+
apiProvider: ollama # The name of the API provider.
|
54
|
+
dataCollectionEnabled: false # Whether to enable data collection.
|
55
|
+
maxConnections: 10 # The maximum number of connections.
|
56
|
+
modelName: llama3.1:latest # The name and version of the AI model to use.
|
57
|
+
name: twinnydotdev # Your chosen name as a provider on the Symmetry network.
|
58
|
+
path: /home/twinnydotdev/.config/symmetry/data # The local path where Symmetry will store its configuration and data files.
|
59
|
+
public: true # Whether this provider is publicly accessible on the Symmetry network.
|
60
|
+
serverKey: 4b4a9cc325d134dee6679e9407420023531fd7e96c563f6c5d00fd5549b77435 # The unique key for connecting to the Symmetry server.
|
58
61
|
```
|
59
62
|
|
60
|
-
Adjust these
|
63
|
+
Adjust these settings according to your preferences and setup.
|
61
64
|
|
62
65
|
## Architecture
|
63
66
|
|
@@ -88,80 +91,46 @@ graph TB
|
|
88
91
|
|
89
92
|
C1 <--> |"4. Inference<br/>Request/Response"| P2
|
90
93
|
C2 <--> |"4. Inference<br/>Request/Response"| P3
|
91
|
-
|
92
|
-
style S fill:#ff9900,stroke:#333,stroke-width:4px
|
93
|
-
style P1 fill:#00ccff,stroke:#333,stroke-width:2px
|
94
|
-
style P2 fill:#00ccff,stroke:#333,stroke-width:2px
|
95
|
-
style P3 fill:#00ccff,stroke:#333,stroke-width:2px
|
96
|
-
style C1 fill:#333,stroke:#fff,stroke-width:2px
|
97
|
-
style C2 fill:#333,stroke:#fff,stroke-width:2px
|
98
94
|
```
|
99
95
|
|
100
|
-
|
101
|
-
- **Central Server**: Symmetry Server, a beacon of order in the chaotic digital winds.
|
102
|
-
- **Providers**: Inference Providers, keepers of knowledge and computational might.
|
103
|
-
- **Client**: Clients, adventurers in search of answers from the oracles of data.
|
104
|
-
|
105
|
-
### Connection:
|
106
|
-
|
107
|
-
1. The Providers approach the Central Tower, proving their worth and declaring their specialties.
|
108
|
-
2. Seekers call out to the Tower, their questions echoing in the digital void.
|
109
|
-
3. The Tower, in its wisdom, guides each Seeker to a suitable Provider.
|
110
|
-
4. Seeker and Provider join in a dance of query and response, their connection direct and true.
|
111
|
-
|
112
|
-
### Communication:
|
113
|
-
|
114
|
-
- All messages between Seekers and Providers are cloaked in unbreakable encryption, safe from prying eyes.
|
115
|
-
- The Providers may choose to remember the tales told to them, a choice they must declare openly.
|
116
|
-
- Seekers are granted the wisdom to choose their Providers based on these declarations of memory.
|
96
|
+
## Development
|
117
97
|
|
118
|
-
|
98
|
+
To set up Symmetry for development:
|
119
99
|
|
120
|
-
|
121
|
-
|
122
|
-
- **Guardianship**: Only the worthy may enter this circle of trust.
|
123
|
-
- **Balance**: The Tower ensures no single Provider bears too heavy a burden.
|
124
|
-
- **Growth**: New Providers may join the circle, expanding the realm of possibility.
|
125
|
-
|
126
|
-
Thus does Symmetry weave its web of connections, bringing together the seekers and keepers of digital wisdom in a grand tapestry of knowledge and computation.
|
127
|
-
|
128
|
-
## Forging of Symmetry
|
129
|
-
|
130
|
-
For those who wish to shape Symmetry with their own hands:
|
131
|
-
|
132
|
-
1. Summon the essence:
|
133
|
-
```
|
100
|
+
1. Clone the repository:
|
101
|
+
```bash
|
134
102
|
git clone https://github.com/twinnydotdev/symmetry.git
|
135
103
|
cd symmetry
|
136
104
|
```
|
137
105
|
|
138
|
-
2.
|
139
|
-
```
|
106
|
+
2. Install dependencies:
|
107
|
+
```bash
|
140
108
|
npm install
|
141
109
|
```
|
142
110
|
|
143
|
-
3.
|
144
|
-
```
|
111
|
+
3. Build the project:
|
112
|
+
```bash
|
145
113
|
npm run build
|
146
114
|
```
|
147
115
|
|
148
|
-
4.
|
149
|
-
```
|
150
|
-
npm
|
116
|
+
4. Start the development server:
|
117
|
+
```bash
|
118
|
+
npm run dev
|
151
119
|
```
|
152
120
|
|
153
|
-
##
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
Contributions are welcome! Please submit your pull requests to the [GitHub repository](https://github.com/twinnydotdev/symmetry/pulls).
|
154
124
|
|
155
|
-
|
125
|
+
## License
|
156
126
|
|
157
|
-
|
127
|
+
This project is licensed under the [MIT License](https://github.com/twinnydotdev/symmetry/blob/master/LICENCE).
|
158
128
|
|
159
|
-
|
129
|
+
## Support
|
160
130
|
|
161
|
-
|
131
|
+
If you encounter any issues or have questions, please [open an issue](https://github.com/twinnydotdev/symmetry/issues) on GitHub.
|
162
132
|
|
163
|
-
|
133
|
+
## Acknowledgments
|
164
134
|
|
165
|
-
|
135
|
+
We thank [Hyperswarm](https://github.com/holepunchto/hyperswarm) for providing the underlying peer-to-peer networking capabilities.
|
166
136
|
|
167
|
-
We pay homage to [Hyperswarm](https://github.com/holepunchto/hyperswarm), the tool that makes our connections possible.
|
package/src/provider.ts
CHANGED
@@ -13,10 +13,8 @@ import {
|
|
13
13
|
safeParseStreamResponse,
|
14
14
|
} from "./utils";
|
15
15
|
import { logger } from "./logger";
|
16
|
-
import { Peer, ProviderMessage, InferenceRequest } from "./types";
|
17
|
-
import {
|
18
|
-
serverMessageKeys,
|
19
|
-
} from "./constants";
|
16
|
+
import { Peer, ProviderMessage, InferenceRequest, Message } from "./types";
|
17
|
+
import { serverMessageKeys } from "./constants";
|
20
18
|
|
21
19
|
export class SymmetryProvider {
|
22
20
|
private _challenge: Buffer | null = null;
|
@@ -192,13 +190,24 @@ export class SymmetryProvider {
|
|
192
190
|
});
|
193
191
|
}
|
194
192
|
|
193
|
+
private getMessagesWithSystem(messages: Message[]): Message[] {
|
194
|
+
const systemMessage = this._config.get("systemMessage")
|
195
|
+
if (messages.length === 2 && systemMessage) {
|
196
|
+
messages.unshift({
|
197
|
+
role: "system",
|
198
|
+
content: systemMessage,
|
199
|
+
});
|
200
|
+
}
|
201
|
+
return messages;
|
202
|
+
}
|
203
|
+
|
195
204
|
private async handleInferenceRequest(
|
196
205
|
data: ProviderMessage<InferenceRequest>,
|
197
206
|
peer: Peer
|
198
207
|
): Promise<void> {
|
199
208
|
const emitterKey = data.data.key;
|
200
|
-
|
201
|
-
const req = this.buildStreamRequest(
|
209
|
+
const messages = this.getMessagesWithSystem(data?.data.messages);
|
210
|
+
const req = this.buildStreamRequest(messages);
|
202
211
|
|
203
212
|
if (!req) return;
|
204
213
|
|
@@ -277,7 +286,7 @@ export class SymmetryProvider {
|
|
277
286
|
private async saveCompletion(
|
278
287
|
completion: string,
|
279
288
|
peer: Peer,
|
280
|
-
messages:
|
289
|
+
messages: Message[]
|
281
290
|
) {
|
282
291
|
fs.writeFile(
|
283
292
|
`${this._config.get("path")}/${peer.publicKey.toString("hex")}-${
|
@@ -296,7 +305,7 @@ export class SymmetryProvider {
|
|
296
305
|
);
|
297
306
|
}
|
298
307
|
|
299
|
-
private buildStreamRequest(messages:
|
308
|
+
private buildStreamRequest(messages: Message[]) {
|
300
309
|
const requestOptions = {
|
301
310
|
hostname: this._config.get("apiHostname"),
|
302
311
|
port: Number(this._config.get("apiPort")),
|
package/src/types.ts
CHANGED
@@ -18,6 +18,7 @@ export interface ProviderConfig {
|
|
18
18
|
port: number;
|
19
19
|
public: boolean;
|
20
20
|
serverKey: string;
|
21
|
+
systemMessage: string;
|
21
22
|
}
|
22
23
|
|
23
24
|
export interface ProviderMessage<T = unknown> {
|
@@ -27,7 +28,7 @@ export interface ProviderMessage<T = unknown> {
|
|
27
28
|
|
28
29
|
export interface InferenceRequest {
|
29
30
|
key: string;
|
30
|
-
messages:
|
31
|
+
messages: Message[];
|
31
32
|
}
|
32
33
|
|
33
34
|
interface ReadableState {
|