Линейные цепочки рассуждений (Linear Chain-of-Thought) обладают фундаментальным ограничением: они реализуют жадный локальный поиск (Greedy Depth-First Search без возврата). Если на раннем шаге генерации модель сделала неоптимальный выбор базового фундаментального паттерна (например, выбрала синхронный RPC вместо событийной хореографии для распределенной транзакции с высокой задержкой), вся последующая цепочка рассуждений посвящается попыткам скомпенсировать архитектурный изъян вторичными заплатками.
Реальное системное проектирование (System Design) принципиально нелинейно. Оно требует исследования дерева компромиссов (Trade-off Matrix), где каждое проектное решение в точке ветвления меняет свойства распределенной системы (CAP/PACELC-теоремы, характеристики консистентности, топологию отказов):
Линейный CoT (Локальный тупик):
[Архитектурная задача] ──► [Выбор REST API] ──► [Проблема тайм-аутов] ──► [Костыли ретраев] ──► [Каскадный сбой]
Tree-of-Thoughts / MCTS (Глобальный поиск по дереву):
[Архитектурная задача]
│
┌─────────────────────────────┼─────────────────────────────┐
▼ ▼ ▼
[Вариант A: REST] [Вариант B: gRPC] [Вариант C: Event-Driven]
│ │ │
(Провал SLA) (Проблема рефлексии) │
▼
┌─────────────────┴─────────────────┐
▼ ▼
[Kafka (Event Streaming)] [RabbitMQ (AMQP)]
│ │
(Высокий TCO) (Оптимальный скор: 0.92)Парадигма Tree-of-Thoughts (ToT) в комбинации с алгоритмом Monte Carlo Tree Search (MCTS) переносит методы поиска на графах состояний в область работы с языковыми моделями. Вместо генерации единого текста система разворачивает архитектурное пространство в виде ориентированного дерева решений, где:
Алгоритм MCTS выполняет итеративный поиск оптимума через четыре канонические фазы:
1. SELECTION 2. EXPANSION 3. SIMULATION 4. BACKPROPAGATION
(Выбор по UCB1) (Генерация дочерних) (Оценка ветви Rollout) (Обновление Q и N вверх)
( Root ) ( Root ) ( Root ) ( Root ) [Q=2.7, N=3]
/ \ / \ / \ / \
(A) (B)* (A) (B) (A) (B) (A) (B)* [Q=1.8, N=2]
[N=1] [N=1] [N=1] [N=1] [N=1] [N=1] [N=1] [N=2]
/ \ / \ / \
(B1)* (B2) (B1) (B2) (B1)* (B2)
│ [Q=0.9, N=1]
▼
[ Rollout ]
Score = 0.90Формула UCB1 (Upper Confidence Bound 1) математически разрешает дилемму «исследование неизведанного против эксплуатации лучшего» (Exploration vs Exploitation):
UCB1(node) = (Q(node) / N(node)) + C * sqrt( ln(N(parent)) / N(node) )Где:
Q(node) / N(node) — эксплуатационная составляющая (Exploitation): средняя оценка полезности решений в данной подветке.C * sqrt(ln(N(parent)) / N(node)) — исследовательская составляющая (Exploration): штраф за редкость посещения узла, стимулирующий проверку альтернативных веток.C — коэффициент баланса (теоретический оптимум: sqrt(2) ≈ 1.414).user_id против составного шардинга по region_id + hash(tenant_id) с расчетом влияния cross-shard транзакций на задержку чтения.Ниже представлена реализация полнофункционального движка ArchitecturalMCTSEngine на TypeScript. Движок реализует все 4 фазы MCTS, использует строгие типы, формулу UCB1 и интегрирован со Zod для валидации контрактов узлов.
import { z } from "zod";
export const ArchitecturalDecisionSchema = z.object({
component: z.string(),
technologyChoice: z.string(),
rationale: z.string(),
tradeoffs: z.object({
advantages: z.array(z.string()),
risks: z.array(z.string()),
latencyImpactMs: z.number(),
infrastructureCostMonthlyUsd: z.number(),
}),
suitabilityScore: z.number().min(0).max(1),
});
export type ArchitecturalDecision = z.infer<typeof ArchitecturalDecisionSchema>;
/**
* Узел дерева поиска MCTS
*/
export class MCTSNode {
public readonly id: string;
public readonly parent: MCTSNode | null;
public readonly children: MCTSNode[] = [];
public readonly depth: number;
public visits = 0;
public totalValue = 0;
public readonly stateDescription: string;
public decisionPayload: ArchitecturalDecision | null = null;
constructor(stateDescription: string, parent: MCTSNode | null = null, depth = 0) {
this.id = Math.random().toString(36).substring(2, 9);
this.stateDescription = stateDescription;
this.parent = parent;
this.depth = depth;
}
public get averageValue(): number {
return this.visits === 0 ? 0 : this.totalValue / this.visits;
}
public isLeaf(): boolean {
return this.children.length === 0;
}
public addChild(child: MCTSNode): void {
this.children.push(child);
}
}
export interface MCTSConfig {
maxIterations: number;
explorationConstant: number; // C в формуле UCB1, по умолчанию sqrt(2)
maxDepth: number;
simulationRounds: number;
}
export const DEFAULT_MCTS_CONFIG: MCTSConfig = {
maxIterations: 12,
explorationConstant: Math.SQRT2,
maxDepth: 3,
simulationRounds: 2,
};
/**
* Движок Monte Carlo Tree Search для поиска оптимальной архитектуры
*/
export class ArchitecturalMCTSEngine {
private readonly config: MCTSConfig;
private readonly apiKey: string;
constructor(apiKey: string, config: Partial<MCTSConfig> = {}) {
this.apiKey = apiKey;
this.config = { ...DEFAULT_MCTS_CONFIG, ...config };
}
/**
* Запуск полного цикла архитектурного поиска
*/
public async searchBestArchitecture(systemRequirements: string): Promise<{
bestTrajectory: ArchitecturalDecision[];
rootNode: MCTSNode;
totalEvaluations: number;
}> {
const root = new MCTSNode(`Root: Requirements = ${systemRequirements}`, null, 0);
for (let iteration = 0; iteration < this.config.maxIterations; iteration++) {
// 1. SELECTION: Спуск от корня к самому перспективному листовому узлу по UCB1
const selectedLeaf = this.selectPromisingNode(root);
// Проверка достижения максимальной глубины декомпозиции
if (selectedLeaf.depth >= this.config.maxDepth) {
// Узел уже терминальный, выполняем повторный бэкпропагейшн
this.backpropagate(selectedLeaf, selectedLeaf.averageValue);
continue;
}
// 2. EXPANSION: Генерация альтернативных архитектурных гипотез через LLM
const candidateNodes = await this.expandNode(selectedLeaf, systemRequirements);
if (candidateNodes.length === 0) continue;
// 3. SIMULATION (Rollout): Оценка каждого сгенерированного кандидата
for (const candidate of candidateNodes) {
const rolloutScore = await this.simulateRollout(candidate, systemRequirements);
// 4. BACKPROPAGATION: Распространение оценки вверх до корня
this.backpropagate(candidate, rolloutScore);
}
}
const bestTrajectory = this.extractOptimalPath(root);
return {
bestTrajectory,
rootNode: root,
totalEvaluations: this.config.maxIterations,
};
}
/**
* Выбор узла с максимальным значением UCB1
*/
private selectPromisingNode(node: MCTSNode): MCTSNode {
let current = node;
while (!current.isLeaf()) {
let bestScore = -Infinity;
let selectedChild = current.children[0];
for (const child of current.children) {
const ucbScore = this.calculateUCB1(child, current.visits);
if (ucbScore > bestScore) {
bestScore = ucbScore;
selectedChild = child;
}
}
current = selectedChild;
}
return current;
}
/**
* Расчет Upper Confidence Bound 1 (UCB1)
*/
private calculateUCB1(node: MCTSNode, parentVisits: number): number {
if (node.visits === 0) {
// Непосещенные узлы имеют приоритет для начального исследования
return Infinity;
}
const exploitation = node.averageValue;
const exploration =
this.config.explorationConstant * Math.sqrt(Math.log(parentVisits) / node.visits);
return exploitation + exploration;
}
/**
* Фаза Expansion: генерация 2-3 альтернативных архитектурных вариантов
*/
private async expandNode(node: MCTSNode, requirements: string): Promise<MCTSNode[]> {
const prompt = `
System Requirements: ${requirements}
Current Architectural State: ${node.stateDescription}
Current Depth: ${node.depth}
Generate 2 distinct architectural design decisions for the next subsystem component.
For each decision, provide trade-offs, estimated latency impact, monthly infra cost, and suitability score (0.0 to 1.0).
Return response strictly as a JSON array matching the ArchitecturalDecision schema.
`.trim();
try {
const decisions = await this.callLLMEvaluation(prompt);
const newNodes: MCTSNode[] = [];
for (const dec of decisions) {
const childState = `${node.stateDescription} -> [${dec.component}: ${dec.technologyChoice}]`;
const childNode = new MCTSNode(childState, node, node.depth + 1);
childNode.decisionPayload = dec;
node.addChild(childNode);
newNodes.push(childNode);
}
return newNodes;
} catch {
return [];
}
}
/**
* Фаза Simulation: расчет жизнеспособности архитектурной траектории
*/
private async simulateRollout(node: MCTSNode, requirements: string): Promise<number> {
if (!node.decisionPayload) return 0.5;
// Взвешенная эвристическая оценка: скор соответствия требованиям с учетом накладных расходов
const baseScore = node.decisionPayload.suitabilityScore;
const latencyPenalty = node.decisionPayload.tradeoffs.latencyImpactMs > 200 ? 0.2 : 0;
const costPenalty = node.decisionPayload.tradeoffs.infrastructureCostMonthlyUsd > 5000 ? 0.15 : 0;
const finalRolloutValue = Math.max(0, Math.min(1, baseScore - latencyPenalty - costPenalty));
return finalRolloutValue;
}
/**
* Фаза Backpropagation: распространение награды вверх по иерархии
*/
private backpropagate(leafNode: MCTSNode, reward: number): void {
let current: MCTSNode | null = leafNode;
while (current !== null) {
current.visits += 1;
current.totalValue += reward;
current = current.parent;
}
}
/**
* Извлечение оптимальной траектории на основе максимального числа посещений (Robust Child)
*/
private extractOptimalPath(root: MCTSNode): ArchitecturalDecision[] {
const path: ArchitecturalDecision[] = [];
let current = root;
while (!current.isLeaf()) {
// Наиболее надежный узел (Robust Child) — узел с наибольшим числом посещений
current.children.sort((a, b) => b.visits - a.visits);
current = current.children[0];
if (current.decisionPayload) {
path.push(current.decisionPayload);
}
}
return path;
}
private async callLLMEvaluation(prompt: string): Promise<ArchitecturalDecision[]> {
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": this.apiKey,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-3-7-sonnet-20250219",
max_tokens: 2500,
messages: [{ role: "user", content: prompt }],
system: "You are a Principal Systems Architect. Output strictly JSON array matching the schema.",
}),
});
if (!response.ok) {
throw new Error(`LLM call failed with status ${response.status}`);
}
const data = await response.json();
const text = data.content?.[0]?.text || "[]";
const cleaned = text.replace(/```json\s*|```/g, "").trim();
const ArraySchema = z.array(ArchitecturalDecisionSchema);
return ArraySchema.parse(JSON.parse(cleaned));
}
}Порождение семантически одинаковых архитектурных решений под разными названиями (например, ветка 1: «RabbitMQ с AMQP», ветка 2: «AMQP-брокер на базе RabbitMQ»). MCTS тратит вычислительный бюджет на раздельное исследование двух идентичных пространств. Необходимо хэшировать технологические кортежи и проверять узел на эквивалентность перед добавлением в дерево.
Установка значения explorationConstant > 3.0. Приводит к вырождению MCTS в хаотичный поиск в ширину (Breadth-First Search). Движок непрерывно генерирует новые поверхностные ветки, не углубляясь в детальную проработку и верификацию выбранной магистральной архитектуры. Рекомендуется диапазон 1.0 <= C <= 1.5.
Выбор лучшего решения по формуле max(averageValue) вместо max(visits). В ветку с пиковым скором 0.99 мог попасть единичный rollout со случайной благоприятной оценкой LLM (ложноположительный исход). Число посещений visits является статистически устойчивой метрикой, доказывающей, что ветка стабильно выдерживала многократные симуляции.
Оценка каждого компонента изолированно. Если в одном решении MCTS выбрал Kafka для событий, Cassandra для временных рядов, Neo4j для графов и CockroachDB для транзакций, каждый узел по отдельности может иметь высокий балл, но суммарная эксплуатационная сложность (TCO) приведет к краху поддержки системы. В фазу Rollout необходимо закладывать штраф за разнородность технологического стека.
Формализация системных требований, ограничений по SLA, бюджетов и целевого RPS
Спуск по дереву с математическим балансированием проверенных узлов и новых альтернатив
LLM-генерация ортогональных технологических решений для следующего уровня декомпозиции
Быстрая симуляция устойчивости стека к нагрузке, сетевым отказам и финансовой стоимости
Инкремент метрик качества вверх до корневого узла для корректировки последующих итераций