solver-sdk 1.7.2 → 1.7.3
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 +175 -458
- package/docs/PING_PONG.md +212 -0
- package/docs/README.md +77 -0
- package/docs/REGIONS.md +140 -0
- package/docs/WEBSOCKET.md +508 -0
- package/docs/WEBSOCKET_EVENTS.md +183 -0
- package/docs/indexing/INDEXING.md +401 -0
- package/docs/thinking/THINKING_ARCHITECTURE.md +221 -0
- package/docs/thinking/streaming-thinking-guide.md +164 -0
- package/docs/thinking/thinking-mode.md +366 -0
- package/package.json +3 -2
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Архитектура системы потоковой передачи мышления
|
|
2
|
+
|
|
3
|
+
Этот документ описывает техническую архитектуру системы потоковой передачи мышления в SDK и взаимодействие между клиентом, сервером и API Anthropic.
|
|
4
|
+
|
|
5
|
+
## Общая схема взаимодействия
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Client (SDK) <--WebSocket--> NestJS Server <--HTTP Stream--> Anthropic API
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Компоненты системы
|
|
12
|
+
|
|
13
|
+
### 1. Клиент (SDK)
|
|
14
|
+
|
|
15
|
+
SDK предоставляет API для:
|
|
16
|
+
- Инициации WebSocket соединения
|
|
17
|
+
- Отправки запросов с активированным режимом мышления
|
|
18
|
+
- Обработки событий через callback-функцию
|
|
19
|
+
- Управления соединениями и сессиями
|
|
20
|
+
|
|
21
|
+
### 2. Сервер (NestJS)
|
|
22
|
+
|
|
23
|
+
Сервер выполняет несколько ключевых функций:
|
|
24
|
+
- Обрабатывает HTTP-запросы от SDK
|
|
25
|
+
- Создает и управляет WebSocket соединениями
|
|
26
|
+
- Отправляет запросы к Anthropic API
|
|
27
|
+
- Преобразует и перенаправляет события от Anthropic API клиентам
|
|
28
|
+
|
|
29
|
+
### 3. Anthropic API
|
|
30
|
+
|
|
31
|
+
API Anthropic предоставляет:
|
|
32
|
+
- Потоковую передачу ответов модели
|
|
33
|
+
- События мышления для моделей, поддерживающих расширенное мышление
|
|
34
|
+
- Различные типы дельта-событий для инкрементальной передачи контента
|
|
35
|
+
|
|
36
|
+
## Порядок работы системы
|
|
37
|
+
|
|
38
|
+
1. **Инициализация WebSocket соединения:**
|
|
39
|
+
- SDK вызывает метод подключения WebSocket
|
|
40
|
+
- Сервер создает соединение и назначает `socketId`
|
|
41
|
+
- SDK сохраняет `socketId` для использования в запросах
|
|
42
|
+
|
|
43
|
+
2. **Отправка запроса на обработку:**
|
|
44
|
+
- SDK отправляет запрос с параметром `thinking: true` и указанным `socketId`
|
|
45
|
+
- Сервер создает сессию рассуждения и связывает ее с WebSocket соединением
|
|
46
|
+
- Сервер инициирует потоковый запрос к Anthropic API
|
|
47
|
+
|
|
48
|
+
3. **Обработка потока данных:**
|
|
49
|
+
- Anthropic API отправляет потоковые события (SSE) серверу
|
|
50
|
+
- Сервер преобразует SSE события в WebSocket события
|
|
51
|
+
- Сервер отправляет события соответствующим клиентам
|
|
52
|
+
|
|
53
|
+
4. **Завершение обработки:**
|
|
54
|
+
- Anthropic API отправляет финальное событие `message_stop`
|
|
55
|
+
- Сервер пересылает событие клиенту и завершает сессию
|
|
56
|
+
- SDK вызывает обработчик `message_stop` и может закрыть соединение
|
|
57
|
+
|
|
58
|
+
## Потоки данных и события
|
|
59
|
+
|
|
60
|
+
### События от Anthropic API
|
|
61
|
+
|
|
62
|
+
Anthropic API отправляет следующие основные типы событий:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
1. message_start
|
|
66
|
+
2. content_block_start (thinking block)
|
|
67
|
+
3. content_block_delta (thinking_delta) x N
|
|
68
|
+
4. content_block_stop
|
|
69
|
+
5. content_block_start (text block)
|
|
70
|
+
6. content_block_delta (text_delta) x M
|
|
71
|
+
7. content_block_stop
|
|
72
|
+
8. message_stop
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Преобразование событий
|
|
76
|
+
|
|
77
|
+
Сервер преобразует события от Anthropic API в формат WebSocket:
|
|
78
|
+
|
|
79
|
+
| Событие Anthropic API | WebSocket событие | Данные |
|
|
80
|
+
|----------------------|-------------------|--------|
|
|
81
|
+
| message_start | message_start | { id, model, type } |
|
|
82
|
+
| content_block_start (thinking) | thinking_block_start | { index, type } |
|
|
83
|
+
| content_block_delta (thinking_delta) | thinking_delta + thinking_block_delta | { text, thinking, index } |
|
|
84
|
+
| content_block_stop (thinking) | thinking_block_stop | { index, type } |
|
|
85
|
+
| content_block_start (text) | content_block_start | { index, type } |
|
|
86
|
+
| content_block_delta (text_delta) | text_delta + content_block_delta | { text, index } |
|
|
87
|
+
| content_block_stop (text) | content_block_stop | { index, type } |
|
|
88
|
+
| message_stop | message_stop | { type } |
|
|
89
|
+
|
|
90
|
+
## Особенности реализации
|
|
91
|
+
|
|
92
|
+
### 1. WebSocket архитектура
|
|
93
|
+
|
|
94
|
+
- Используется Socket.IO для WebSocket коммуникации
|
|
95
|
+
- Соединения организованы по namespace `/reasoning`
|
|
96
|
+
- Используется корректный path `/socket.io` без завершающего слеша
|
|
97
|
+
|
|
98
|
+
### 2. Обработка событий мышления
|
|
99
|
+
|
|
100
|
+
- События мышления (`thinking_delta`) передаются в двух форматах:
|
|
101
|
+
1. `thinking_delta` с полями `text` и `thinking` для совместимости с различными клиентами
|
|
102
|
+
2. `thinking_block_delta` с полем `delta` для совместимости с SDK тестами
|
|
103
|
+
|
|
104
|
+
### 3. Потоки данных
|
|
105
|
+
|
|
106
|
+
Система поддерживает два параллельных потока данных:
|
|
107
|
+
- Поток мышления (отображает процесс рассуждения модели)
|
|
108
|
+
- Поток ответа (финальный ответ модели после рассуждения)
|
|
109
|
+
|
|
110
|
+
### 4. Работа с многопроцессными средами
|
|
111
|
+
|
|
112
|
+
При использовании SDK в многопроцессных средах:
|
|
113
|
+
- WebSocket соединение должно быть инициализировано в одном процессе
|
|
114
|
+
- События должны передаваться между процессами через IPC
|
|
115
|
+
- Необходима буферизация событий для предотвращения потери данных
|
|
116
|
+
|
|
117
|
+
## Диагностика и устранение проблем
|
|
118
|
+
|
|
119
|
+
### Типичные проблемы и их решение
|
|
120
|
+
|
|
121
|
+
| Проблема | Возможные причины | Решение |
|
|
122
|
+
|----------|-------------------|---------|
|
|
123
|
+
| Нет подключения WebSocket | Неверный URL, CORS, блокировка порта | Проверьте сетевые настройки, логи сервера |
|
|
124
|
+
| Не приходят события thinking_delta | Проблема с socketId, неверный формат запроса | Проверьте передачу socketId, включение параметра thinking |
|
|
125
|
+
| Отключение в середине потока | Таймаут, ошибка сервера | Используйте механизм переподключения, проверьте логи сервера |
|
|
126
|
+
| Неправильный формат данных | Несоответствие между версиями клиента и сервера | Обновите SDK или сервер до последней версии |
|
|
127
|
+
|
|
128
|
+
### Диагностические инструменты
|
|
129
|
+
|
|
130
|
+
- Подробные логи на серверной стороне
|
|
131
|
+
- Индикация полученных событий в клиентской части
|
|
132
|
+
- Мониторинг состояния WebSocket соединений
|
|
133
|
+
|
|
134
|
+
## Рекомендации по оптимизации
|
|
135
|
+
|
|
136
|
+
### Клиентская сторона
|
|
137
|
+
|
|
138
|
+
- Используйте буферизацию событий для экономии ресурсов UI
|
|
139
|
+
- Применяйте дедупликацию и фильтрацию повторяющихся событий
|
|
140
|
+
- Добавьте индикаторы прогресса для длительных операций
|
|
141
|
+
|
|
142
|
+
### Серверная сторона
|
|
143
|
+
|
|
144
|
+
- Оптимизируйте структуру данных для минимизации трафика
|
|
145
|
+
- Используйте пулинг WebSocket соединений для высоконагруженных систем
|
|
146
|
+
- Применяйте компрессию данных для больших объемов текста
|
|
147
|
+
|
|
148
|
+
## Примеры использования
|
|
149
|
+
|
|
150
|
+
### Базовый пример
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
// Инициализация SDK и WebSocket
|
|
154
|
+
const sdk = new CodeSolverSDK({ baseURL: 'https://api.example.com' });
|
|
155
|
+
const wsClient = sdk.getWebSocketClient();
|
|
156
|
+
await wsClient.connect();
|
|
157
|
+
|
|
158
|
+
// Обработчик событий
|
|
159
|
+
const handleEvent = (eventType, data) => {
|
|
160
|
+
if (eventType === 'thinking_delta') {
|
|
161
|
+
console.log('Thinking:', data.text || data.thinking);
|
|
162
|
+
} else if (eventType === 'text_delta') {
|
|
163
|
+
console.log('Response:', data.text);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// Отправка запроса с thinking
|
|
168
|
+
const response = await sdk.chat.streamChatWithThinking(
|
|
169
|
+
[{ role: 'user', content: 'Explain quantum computing' }],
|
|
170
|
+
{
|
|
171
|
+
model: 'claude-3-7-sonnet-20240229',
|
|
172
|
+
thinking: true
|
|
173
|
+
},
|
|
174
|
+
handleEvent
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Расширенный пример с обработкой ошибок
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
// Инициализация с обработкой ошибок
|
|
182
|
+
try {
|
|
183
|
+
const wsClient = sdk.getWebSocketClient();
|
|
184
|
+
await wsClient.connect();
|
|
185
|
+
|
|
186
|
+
// Обработчик с поддержкой ошибок
|
|
187
|
+
const handleEvent = (eventType, data) => {
|
|
188
|
+
switch(eventType) {
|
|
189
|
+
case 'thinking_delta':
|
|
190
|
+
updateThinkingUI(data.text || data.thinking);
|
|
191
|
+
break;
|
|
192
|
+
case 'text_delta':
|
|
193
|
+
updateResponseUI(data.text);
|
|
194
|
+
break;
|
|
195
|
+
case 'error':
|
|
196
|
+
showError(`Error: ${data.message}`);
|
|
197
|
+
break;
|
|
198
|
+
case 'disconnect':
|
|
199
|
+
showWarning('Connection lost, attempting to reconnect...');
|
|
200
|
+
reconnect();
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Отправка запроса
|
|
206
|
+
const response = await sdk.chat.streamChatWithThinking(
|
|
207
|
+
messages,
|
|
208
|
+
options,
|
|
209
|
+
handleEvent
|
|
210
|
+
);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error('Failed to connect:', error);
|
|
213
|
+
showFatalError(error.message);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Дополнительные ресурсы
|
|
218
|
+
|
|
219
|
+
- [Документация Anthropic по потоковой передаче](https://docs.anthropic.com/en/api/messages-streaming)
|
|
220
|
+
- [Streaming Thinking Guide](./streaming-thinking-guide.md)
|
|
221
|
+
- [WebSocket Documentation](./WEBSOCKET.md)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Руководство: Потоковый чат с Thinking через SDK
|
|
2
|
+
|
|
3
|
+
Это руководство объясняет, как использовать обновленный `solver-sdk` для получения потоковых ответов от языковой модели с поддержкой режима "thinking" через WebSocket. Это позволяет отображать ход мыслей модели и финальный ответ в реальном времени.
|
|
4
|
+
|
|
5
|
+
## Основной метод: `streamChatWithThinking`
|
|
6
|
+
|
|
7
|
+
Для потоковой передачи с thinking используйте новый метод `sdk.chat.streamChatWithThinking`.
|
|
8
|
+
|
|
9
|
+
**Преимущества:**
|
|
10
|
+
|
|
11
|
+
- **Автоматическое подключение WebSocket:** SDK сам создает и управляет WebSocket соединением.
|
|
12
|
+
- **Простая обработка событий:** Вы просто предоставляете callback-функцию для обработки всех событий потока.
|
|
13
|
+
- **Полная поддержка Anthropic:** Обрабатываются все актуальные события (`thinking_delta`, `text_delta`, `signature_delta`, `message_delta`, `ping` и т.д.).
|
|
14
|
+
|
|
15
|
+
## Пример использования
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const { CodeSolverSDK } = require('solver-sdk'); // Или import { CodeSolverSDK } from 'solver-sdk';
|
|
19
|
+
|
|
20
|
+
async function runStreamingExample() {
|
|
21
|
+
// 1. Инициализация SDK
|
|
22
|
+
const sdk = new CodeSolverSDK({
|
|
23
|
+
baseURL: 'https://your-backend-url.com', // URL вашего бэкенда
|
|
24
|
+
// apiKey: 'your-api-key' // Если требуется
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 2. Сообщения для отправки
|
|
28
|
+
const messages = [
|
|
29
|
+
{ role: 'user', content: 'Объясни теорию относительности простыми словами.' }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// 3. Опции запроса (включаем thinking)
|
|
33
|
+
const options = {
|
|
34
|
+
model: 'claude-3-7-sonnet-20240229', // Или другая модель с поддержкой thinking
|
|
35
|
+
thinking: true, // Обязательно для активации режима
|
|
36
|
+
temperature: 0.7
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// 4. Обработчик событий WebSocket
|
|
40
|
+
const handleEvent = (eventType, data) => {
|
|
41
|
+
console.log(`[EVENT: ${eventType}]`, data); // Логирование всех событий для отладки
|
|
42
|
+
|
|
43
|
+
switch(eventType) {
|
|
44
|
+
// Начало потока
|
|
45
|
+
case 'connect':
|
|
46
|
+
console.log(`WebSocket подключен: ${data.socketId}`);
|
|
47
|
+
break;
|
|
48
|
+
case 'message_start':
|
|
49
|
+
console.log(`Начало ответа модели: ${data.model}`);
|
|
50
|
+
// Здесь можно инициализировать UI для отображения ответа
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
// Поток размышлений
|
|
54
|
+
case 'thinking_start':
|
|
55
|
+
console.log('-- Начало размышлений --');
|
|
56
|
+
// Очистить/показать область для размышлений
|
|
57
|
+
break;
|
|
58
|
+
case 'thinking_delta':
|
|
59
|
+
process.stdout.write(data.text); // Выводим текст размышлений по мере поступления
|
|
60
|
+
// Добавить data.text в UI область размышлений
|
|
61
|
+
break;
|
|
62
|
+
case 'signature_delta':
|
|
63
|
+
console.log('[Подпись блока thinking получена]');
|
|
64
|
+
break;
|
|
65
|
+
|
|
66
|
+
// Поток основного ответа
|
|
67
|
+
case 'text_delta':
|
|
68
|
+
process.stdout.write(data.text); // Выводим текст ответа по мере поступления
|
|
69
|
+
// Добавить data.text в UI область ответа
|
|
70
|
+
break;
|
|
71
|
+
|
|
72
|
+
// Завершение блоков и сообщения
|
|
73
|
+
case 'content_block_stop':
|
|
74
|
+
// Блок (thinking или text) завершен
|
|
75
|
+
break;
|
|
76
|
+
case 'message_delta':
|
|
77
|
+
// Обновление статуса сообщения (например, stop_reason)
|
|
78
|
+
console.log(`Обновление сообщения: ${JSON.stringify(data.delta)}`);
|
|
79
|
+
break;
|
|
80
|
+
case 'message_stop':
|
|
81
|
+
console.log('-- Сообщение завершено --');
|
|
82
|
+
// Показать финальное состояние UI
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
// Служебные события
|
|
86
|
+
case 'ping':
|
|
87
|
+
console.log('[Ping от сервера]');
|
|
88
|
+
break;
|
|
89
|
+
case 'retry':
|
|
90
|
+
console.warn(`Попытка переподключения ${data.retryCount} из-за перегрузки...`);
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
// Ошибки и завершение
|
|
94
|
+
case 'error':
|
|
95
|
+
console.error(`Ошибка WebSocket: ${data.message} (Код: ${data.code})`);
|
|
96
|
+
// Показать сообщение об ошибке в UI
|
|
97
|
+
break;
|
|
98
|
+
case 'disconnect':
|
|
99
|
+
console.log('WebSocket отключен');
|
|
100
|
+
break;
|
|
101
|
+
case 'done':
|
|
102
|
+
console.log('Поток данных завершен.');
|
|
103
|
+
// Можно закрыть соединение или ожидать новых запросов
|
|
104
|
+
break;
|
|
105
|
+
|
|
106
|
+
case 'unknown_event':
|
|
107
|
+
console.log(`Получено неизвестное событие: ${data.type}`);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// 5. Вызов метода и ожидание потока
|
|
113
|
+
try {
|
|
114
|
+
console.log('Отправка запроса...');
|
|
115
|
+
const response = await sdk.chat.streamChatWithThinking(
|
|
116
|
+
messages,
|
|
117
|
+
options,
|
|
118
|
+
handleEvent // Передаем наш обработчик
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
console.log(`Запрос успешно отправлен. Используется Socket ID: ${response.socketId}`);
|
|
122
|
+
console.log('Ожидание событий через WebSocket...');
|
|
123
|
+
// В реальном приложении здесь будет основной цикл работы или ожидание
|
|
124
|
+
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('Ошибка при отправке запроса:', error);
|
|
127
|
+
// Обработка ошибки инициации запроса
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Запуск примера
|
|
132
|
+
runStreamingExample();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Ключевые моменты
|
|
136
|
+
|
|
137
|
+
1. **Включите `thinking: true`**: Это главный параметр для активации режима потокового мышления.
|
|
138
|
+
2. **Предоставьте обработчик `onEvent`**: Эта функция будет получать все события WebSocket.
|
|
139
|
+
3. **Обрабатывайте нужные события**: Как минимум, вам понадобятся `thinking_delta` (для размышлений) и `text_delta` (для основного ответа), а также `error` и `done`.
|
|
140
|
+
4. **SDK управляет соединением**: Вам не нужно вручную создавать `socketId` или подключаться к WebSocket – SDK сделает это автоматически.
|
|
141
|
+
|
|
142
|
+
## (Опционально) Использование существующего `socketId`
|
|
143
|
+
|
|
144
|
+
Если ваш клиент уже управляет WebSocket соединением и имеет `socketId`, вы можете передать его в опциях, чтобы SDK использовал существующее соединение:
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Предположим, у вас есть connectResponse от sdk.chat.connectWebSocket()
|
|
148
|
+
const existingSocketId = connectResponse.socketId;
|
|
149
|
+
|
|
150
|
+
const options = {
|
|
151
|
+
model: 'claude-3-7-sonnet-20240229',
|
|
152
|
+
thinking: true,
|
|
153
|
+
socketId: existingSocketId // Передаем существующий ID
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// SDK не будет создавать новое соединение, а использует указанное
|
|
157
|
+
const response = await sdk.chat.streamChatWithThinking(
|
|
158
|
+
messages,
|
|
159
|
+
options,
|
|
160
|
+
handleEvent
|
|
161
|
+
);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Это полезно, если вы хотите использовать одно WebSocket соединение для нескольких запросов.
|