503
src/tools/circuit-tools.ts
Archivo normal
503
src/tools/circuit-tools.ts
Archivo normal
@@ -0,0 +1,503 @@
|
||||
/**
|
||||
* Quantum Circuit Building Tools for MCP Server
|
||||
* Provides tools for creating and manipulating quantum circuits
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import {
|
||||
CreateKernelSchema,
|
||||
ApplyGateSchema,
|
||||
CreateKernelInput,
|
||||
ApplyGateInput
|
||||
} from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('QuantumCircuitTools');
|
||||
|
||||
/**
|
||||
* Tool for creating a new quantum kernel/circuit
|
||||
*/
|
||||
export const createQuantumKernelTool: Tool = {
|
||||
name: 'create_quantum_kernel',
|
||||
description: 'Create a new quantum kernel (circuit) with specified number of qubits and optional parameters',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
num_qubits: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 32,
|
||||
description: 'Number of qubits in the quantum register'
|
||||
},
|
||||
parameters: {
|
||||
type: 'array',
|
||||
description: 'Optional parameters for the kernel',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
type: {
|
||||
type: 'string',
|
||||
enum: ['int', 'float', 'complex', 'list[int]', 'list[float]', 'list[complex]']
|
||||
},
|
||||
default: { description: 'Default value for the parameter' }
|
||||
},
|
||||
required: ['name', 'type']
|
||||
}
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'Optional description of the kernel'
|
||||
}
|
||||
},
|
||||
required: ['name', 'num_qubits']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for applying quantum gates to a kernel
|
||||
*/
|
||||
export const applyQuantumGateTool: Tool = {
|
||||
name: 'apply_quantum_gate',
|
||||
description: 'Apply a quantum gate to specified qubits in a quantum kernel',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to modify'
|
||||
},
|
||||
gate_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum gate to apply',
|
||||
enum: ['h', 'x', 'y', 'z', 's', 't', 'rx', 'ry', 'rz', 'cx', 'cy', 'cz', 'ccx', 'swap', 'cswap']
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
description: 'Indices of qubits to apply the gate to',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
parameters: {
|
||||
type: 'array',
|
||||
description: 'Parameters for parameterized gates (e.g., rotation angles)',
|
||||
items: { type: 'number' }
|
||||
},
|
||||
controls: {
|
||||
type: 'array',
|
||||
description: 'Control qubits for controlled operations',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
adjoint: {
|
||||
type: 'boolean',
|
||||
description: 'Apply adjoint (inverse) of the gate',
|
||||
default: false
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'gate_name', 'qubits']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for adding measurements to a quantum kernel
|
||||
*/
|
||||
export const addMeasurementTool: Tool = {
|
||||
name: 'add_measurement',
|
||||
description: 'Add quantum measurements to a kernel',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
description: 'Qubits to measure (empty array means measure all)',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
basis: {
|
||||
type: 'string',
|
||||
description: 'Measurement basis',
|
||||
enum: ['Z', 'X', 'Y'],
|
||||
default: 'Z'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for creating common quantum circuits
|
||||
*/
|
||||
export const createCommonCircuitTool: Tool = {
|
||||
name: 'create_common_circuit',
|
||||
description: 'Create commonly used quantum circuits (GHZ, Bell states, QFT, etc.)',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
circuit_type: {
|
||||
type: 'string',
|
||||
description: 'Type of quantum circuit to create',
|
||||
enum: ['bell_pair', 'ghz_state', 'quantum_fourier_transform', 'grover_oracle', 'hadamard_test']
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name for the created kernel'
|
||||
},
|
||||
num_qubits: {
|
||||
type: 'integer',
|
||||
minimum: 2,
|
||||
maximum: 32,
|
||||
description: 'Number of qubits (where applicable)'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Circuit-specific parameters'
|
||||
}
|
||||
},
|
||||
required: ['circuit_type', 'name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for listing available quantum kernels
|
||||
*/
|
||||
export const listQuantumKernelsTool: Tool = {
|
||||
name: 'list_quantum_kernels',
|
||||
description: 'List all available quantum kernels and their metadata',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
detailed: {
|
||||
type: 'boolean',
|
||||
description: 'Include detailed metadata about each kernel',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for visualizing quantum circuits
|
||||
*/
|
||||
export const visualizeCircuitTool: Tool = {
|
||||
name: 'visualize_circuit',
|
||||
description: 'Generate a text-based visualization of a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to visualize'
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
description: 'Output format for the visualization',
|
||||
enum: ['text', 'qasm', 'json'],
|
||||
default: 'text'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions for the tools
|
||||
*/
|
||||
|
||||
export async function handleCreateQuantumKernel(input: CreateKernelInput) {
|
||||
try {
|
||||
// Validate input
|
||||
const validatedInput = CreateKernelSchema.parse(input);
|
||||
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.createKernel(
|
||||
validatedInput.name,
|
||||
validatedInput.num_qubits,
|
||||
validatedInput.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
logger.info(`Created quantum kernel: ${validatedInput.name} with ${validatedInput.num_qubits} qubits`);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully created quantum kernel '${validatedInput.name}' with ${validatedInput.num_qubits} qubits.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to create quantum kernel');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error creating quantum kernel:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error creating quantum kernel: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleApplyQuantumGate(input: ApplyGateInput) {
|
||||
try {
|
||||
const validatedInput = ApplyGateSchema.parse(input);
|
||||
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.applyGate(
|
||||
validatedInput.kernel_name,
|
||||
validatedInput.gate_name,
|
||||
validatedInput.qubits,
|
||||
validatedInput.parameters,
|
||||
validatedInput.controls,
|
||||
validatedInput.adjoint
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const gateDesc = validatedInput.controls
|
||||
? `controlled ${validatedInput.gate_name}`
|
||||
: validatedInput.gate_name;
|
||||
|
||||
logger.info(`Applied ${gateDesc} gate to kernel ${validatedInput.kernel_name}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully applied ${gateDesc} gate to qubits [${validatedInput.qubits.join(', ')}] in kernel '${validatedInput.kernel_name}'.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to apply quantum gate');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error applying quantum gate:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error applying quantum gate: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleAddMeasurement(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// For now, measurements are added automatically by CUDA Quantum
|
||||
// This tool documents the measurement intention
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Measurements will be applied to kernel '${input.kernel_name}' in ${input.basis || 'Z'} basis. CUDA Quantum automatically measures all qubits if no explicit measurements are specified.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error adding measurement:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error adding measurement: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleCreateCommonCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// Create the kernel first
|
||||
const numQubits = input.num_qubits || (input.circuit_type === 'bell_pair' ? 2 : 3);
|
||||
|
||||
let kernelResponse = await bridge.createKernel(input.name, numQubits);
|
||||
if (!kernelResponse.success) {
|
||||
throw new Error(kernelResponse.error || 'Failed to create kernel');
|
||||
}
|
||||
|
||||
// Apply gates based on circuit type
|
||||
switch (input.circuit_type) {
|
||||
case 'bell_pair':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
await bridge.applyGate(input.name, 'x', [1], undefined, [0]);
|
||||
break;
|
||||
|
||||
case 'ghz_state':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
for (let i = 1; i < numQubits; i++) {
|
||||
await bridge.applyGate(input.name, 'x', [i], undefined, [0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'hadamard_test':
|
||||
await bridge.applyGate(input.name, 'h', [0]);
|
||||
// Additional gates would depend on the operator being tested
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported circuit type: ${input.circuit_type}`);
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Successfully created ${input.circuit_type} circuit named '${input.name}' with ${numQubits} qubits.`
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error creating common circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error creating common circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleListQuantumKernels(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.listKernels();
|
||||
|
||||
if (response.success) {
|
||||
const kernels = response.kernels || [];
|
||||
const metadata = response.metadata || {};
|
||||
|
||||
if (kernels.length === 0) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: 'No quantum kernels available. Create a kernel first using create_quantum_kernel.'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
let output = `Available quantum kernels (${kernels.length}):\n\n`;
|
||||
|
||||
for (const kernelName of kernels) {
|
||||
const meta = metadata[kernelName] || {};
|
||||
output += `• ${kernelName}\n`;
|
||||
|
||||
if (input.detailed && meta) {
|
||||
output += ` - Qubits: ${meta.num_qubits || 'Unknown'}\n`;
|
||||
output += ` - Parameters: ${meta.parameters?.length || 0}\n`;
|
||||
output += ` - Operations: ${meta.operations?.length || 0}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to list kernels');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error listing quantum kernels:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error listing quantum kernels: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleVisualizeCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.listKernels();
|
||||
|
||||
if (!response.success || !response.kernels?.includes(input.kernel_name)) {
|
||||
throw new Error(`Kernel '${input.kernel_name}' not found`);
|
||||
}
|
||||
|
||||
const metadata = response.metadata?.[input.kernel_name];
|
||||
if (!metadata) {
|
||||
throw new Error(`No metadata available for kernel '${input.kernel_name}'`);
|
||||
}
|
||||
|
||||
// Generate simple text visualization
|
||||
let circuit = `Quantum Circuit: ${input.kernel_name}\n`;
|
||||
circuit += `Qubits: ${metadata.num_qubits}\n\n`;
|
||||
|
||||
const operations = metadata.operations || [];
|
||||
if (operations.length === 0) {
|
||||
circuit += 'No operations applied yet.\n';
|
||||
} else {
|
||||
circuit += 'Operations:\n';
|
||||
operations.forEach((op: any, index: number) => {
|
||||
const controls = op.controls ? ` (ctrl: ${op.controls.join(',')})` : '';
|
||||
const params = op.parameters ? ` (${op.parameters.join(',')})` : '';
|
||||
circuit += `${index + 1}. ${op.gate.toUpperCase()}${params} → qubits[${op.qubits.join(',')}]${controls}\n`;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: circuit
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error visualizing circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error visualizing circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const quantumCircuitTools: Tool[] = [
|
||||
createQuantumKernelTool,
|
||||
applyQuantumGateTool,
|
||||
addMeasurementTool,
|
||||
createCommonCircuitTool,
|
||||
listQuantumKernelsTool,
|
||||
visualizeCircuitTool
|
||||
];
|
||||
532
src/tools/execution-tools.ts
Archivo normal
532
src/tools/execution-tools.ts
Archivo normal
@@ -0,0 +1,532 @@
|
||||
/**
|
||||
* Quantum Execution Tools for MCP Server
|
||||
* Provides tools for executing quantum circuits and obtaining results
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { ExecuteKernelSchema, ExecuteKernelInput } from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('QuantumExecutionTools');
|
||||
|
||||
/**
|
||||
* Tool for sampling quantum circuits
|
||||
*/
|
||||
export const sampleQuantumCircuitTool: Tool = {
|
||||
name: 'sample_quantum_circuit',
|
||||
description: 'Sample measurement results from a quantum circuit execution',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to execute'
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of measurement shots'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
description: 'Quantum execution target',
|
||||
default: 'qpp-cpu'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for computing expectation values
|
||||
*/
|
||||
export const observeHamiltonianTool: Tool = {
|
||||
name: 'observe_hamiltonian',
|
||||
description: 'Compute the expectation value of a Hamiltonian using a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel to use'
|
||||
},
|
||||
hamiltonian_terms: {
|
||||
type: 'array',
|
||||
description: 'Pauli terms defining the Hamiltonian',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paulis: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: ['I', 'X', 'Y', 'Z']
|
||||
}
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
coefficient: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
real: { type: 'number' },
|
||||
imag: { type: 'number' }
|
||||
},
|
||||
required: ['real', 'imag']
|
||||
}
|
||||
},
|
||||
required: ['paulis', 'qubits', 'coefficient']
|
||||
}
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of measurement shots'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'hamiltonian_terms']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for getting quantum state vectors
|
||||
*/
|
||||
export const getQuantumStateTool: Tool = {
|
||||
name: 'get_quantum_state',
|
||||
description: 'Get the quantum state vector from a quantum circuit',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
enum: ['amplitudes', 'probabilities', 'both'],
|
||||
default: 'amplitudes',
|
||||
description: 'Output format for the state'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for running quantum algorithms
|
||||
*/
|
||||
export const runQuantumAlgorithmTool: Tool = {
|
||||
name: 'run_quantum_algorithm',
|
||||
description: 'Execute quantum algorithms with custom return values',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the quantum kernel'
|
||||
},
|
||||
shots: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100000,
|
||||
default: 1000,
|
||||
description: 'Number of executions'
|
||||
},
|
||||
parameters: {
|
||||
type: 'object',
|
||||
description: 'Parameters to pass to the quantum kernel'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for quantum variational optimization
|
||||
*/
|
||||
export const variationalOptimizationTool: Tool = {
|
||||
name: 'variational_optimization',
|
||||
description: 'Perform variational quantum optimization using gradient-based methods',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
kernel_name: {
|
||||
type: 'string',
|
||||
description: 'Name of the parameterized quantum kernel'
|
||||
},
|
||||
hamiltonian_terms: {
|
||||
type: 'array',
|
||||
description: 'Hamiltonian terms for the cost function',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paulis: {
|
||||
type: 'array',
|
||||
items: { type: 'string', enum: ['I', 'X', 'Y', 'Z'] }
|
||||
},
|
||||
qubits: {
|
||||
type: 'array',
|
||||
items: { type: 'integer', minimum: 0 }
|
||||
},
|
||||
coefficient: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
real: { type: 'number' },
|
||||
imag: { type: 'number' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
initial_parameters: {
|
||||
type: 'array',
|
||||
description: 'Initial parameter values',
|
||||
items: { type: 'number' }
|
||||
},
|
||||
optimizer: {
|
||||
type: 'string',
|
||||
enum: ['cobyla', 'l-bfgs-b', 'gradient-descent'],
|
||||
default: 'cobyla',
|
||||
description: 'Optimization algorithm'
|
||||
},
|
||||
max_iterations: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 1000,
|
||||
default: 100,
|
||||
description: 'Maximum optimization iterations'
|
||||
}
|
||||
},
|
||||
required: ['kernel_name', 'hamiltonian_terms', 'initial_parameters']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions
|
||||
*/
|
||||
|
||||
export async function handleSampleQuantumCircuit(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// Set target if specified
|
||||
if (input.target) {
|
||||
await bridge.setTarget(input.target);
|
||||
}
|
||||
|
||||
const response = await bridge.sample(
|
||||
input.kernel_name,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const counts = result.counts || {};
|
||||
const shots = result.shots || input.shots || 1000;
|
||||
|
||||
// Format results
|
||||
let output = `Sampling Results for '${input.kernel_name}':\n\n`;
|
||||
output += `Shots: ${shots}\n`;
|
||||
output += `Results:\n`;
|
||||
|
||||
const sortedStates = Object.entries(counts).sort((a, b) => (b[1] as number) - (a[1] as number));
|
||||
|
||||
for (const [state, count] of sortedStates) {
|
||||
const probability = ((count as number) / shots * 100).toFixed(2);
|
||||
output += ` |${state}⟩: ${count} (${probability}%)\n`;
|
||||
}
|
||||
|
||||
// Calculate entropy
|
||||
const totalCounts = Object.values(counts).reduce((a, b) => (a as number) + (b as number), 0);
|
||||
let entropy = 0;
|
||||
for (const count of Object.values(counts)) {
|
||||
if ((count as number) > 0) {
|
||||
const p = (count as number) / totalCounts;
|
||||
entropy -= p * Math.log2(p);
|
||||
}
|
||||
}
|
||||
|
||||
output += `\nEntropy: ${entropy.toFixed(3)} bits\n`;
|
||||
|
||||
logger.info(`Sampled quantum circuit ${input.kernel_name} with ${shots} shots`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to sample quantum circuit');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error sampling quantum circuit:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error sampling quantum circuit: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleObserveHamiltonian(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.observe(
|
||||
input.kernel_name,
|
||||
input.hamiltonian_terms,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const expectation = result.expectation;
|
||||
const variance = result.variance;
|
||||
const shots = result.shots || input.shots || 1000;
|
||||
|
||||
let output = `Hamiltonian Expectation Value for '${input.kernel_name}':\n\n`;
|
||||
output += `Expectation Value: ${expectation}\n`;
|
||||
if (variance !== undefined) {
|
||||
output += `Variance: ${variance}\n`;
|
||||
output += `Standard Deviation: ${Math.sqrt(variance).toFixed(6)}\n`;
|
||||
}
|
||||
output += `Shots: ${shots}\n`;
|
||||
|
||||
// Display Hamiltonian terms
|
||||
output += `\nHamiltonian Terms:\n`;
|
||||
input.hamiltonian_terms.forEach((term: any, index: number) => {
|
||||
const coeff = term.coefficient.imag !== 0
|
||||
? `${term.coefficient.real} + ${term.coefficient.imag}i`
|
||||
: `${term.coefficient.real}`;
|
||||
|
||||
const pauli_str = term.paulis.map((p: string, i: number) => `${p}_${term.qubits[i]}`).join(' ⊗ ');
|
||||
output += ` Term ${index + 1}: ${coeff} × (${pauli_str})\n`;
|
||||
});
|
||||
|
||||
logger.info(`Computed expectation value for ${input.kernel_name}: ${expectation}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to observe Hamiltonian');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error observing Hamiltonian:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error observing Hamiltonian: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleGetQuantumState(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.getState(
|
||||
input.kernel_name,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
const state = result.state || [];
|
||||
const dimension = result.dimension || state.length;
|
||||
|
||||
let output = `Quantum State for '${input.kernel_name}':\n\n`;
|
||||
output += `State Vector Dimension: ${dimension}\n`;
|
||||
|
||||
if (input.format === 'probabilities' || input.format === 'both') {
|
||||
output += `\nProbability Amplitudes:\n`;
|
||||
state.forEach((amplitude: any, index: number) => {
|
||||
const prob = amplitude.real * amplitude.real + amplitude.imag * amplitude.imag;
|
||||
if (prob > 1e-10) { // Only show non-negligible amplitudes
|
||||
const binary = index.toString(2).padStart(Math.log2(dimension), '0');
|
||||
output += ` |${binary}⟩: ${(prob * 100).toFixed(4)}%\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (input.format === 'amplitudes' || input.format === 'both') {
|
||||
output += `\nComplex Amplitudes:\n`;
|
||||
state.forEach((amplitude: any, index: number) => {
|
||||
const magnitude = Math.sqrt(amplitude.real * amplitude.real + amplitude.imag * amplitude.imag);
|
||||
if (magnitude > 1e-10) {
|
||||
const binary = index.toString(2).padStart(Math.log2(dimension), '0');
|
||||
const complex_str = amplitude.imag >= 0
|
||||
? `${amplitude.real.toFixed(6)} + ${amplitude.imag.toFixed(6)}i`
|
||||
: `${amplitude.real.toFixed(6)} - ${Math.abs(amplitude.imag).toFixed(6)}i`;
|
||||
output += ` |${binary}⟩: ${complex_str}\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate purity and other properties
|
||||
let purity = 0;
|
||||
for (const amplitude of state) {
|
||||
const prob = amplitude.real * amplitude.real + amplitude.imag * amplitude.imag;
|
||||
purity += prob * prob;
|
||||
}
|
||||
|
||||
output += `\nState Properties:\n`;
|
||||
output += ` Purity: ${purity.toFixed(6)}\n`;
|
||||
output += ` Entanglement: ${purity < 0.99 ? 'Entangled' : 'Separable'}\n`;
|
||||
|
||||
logger.info(`Retrieved quantum state for ${input.kernel_name} (dimension: ${dimension})`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to get quantum state');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error getting quantum state:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error getting quantum state: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleRunQuantumAlgorithm(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
// This would use CUDA Quantum's run() function for kernels that return values
|
||||
// For now, we'll use sample as a placeholder
|
||||
const response = await bridge.sample(
|
||||
input.kernel_name,
|
||||
input.shots || 1000,
|
||||
input.parameters
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
let output = `Quantum Algorithm Execution Results for '${input.kernel_name}':\n\n`;
|
||||
output += `Executions: ${input.shots || 1000}\n`;
|
||||
output += `Status: Completed Successfully\n`;
|
||||
|
||||
// For actual algorithms, this would show algorithm-specific results
|
||||
output += `\nNote: This is a sample-based execution. For algorithms with custom return values, `;
|
||||
output += `implement the kernel with appropriate return statements in CUDA Quantum.\n`;
|
||||
|
||||
logger.info(`Executed quantum algorithm ${input.kernel_name}`);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to run quantum algorithm');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error running quantum algorithm:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error running quantum algorithm: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleVariationalOptimization(input: any) {
|
||||
try {
|
||||
// This is a placeholder for variational optimization
|
||||
// In a full implementation, this would use optimization libraries
|
||||
|
||||
let output = `Variational Optimization for '${input.kernel_name}':\n\n`;
|
||||
output += `Initial Parameters: [${input.initial_parameters.join(', ')}]\n`;
|
||||
output += `Optimizer: ${input.optimizer}\n`;
|
||||
output += `Max Iterations: ${input.max_iterations}\n`;
|
||||
output += `\nNote: Variational optimization requires integration with optimization libraries.\n`;
|
||||
output += `This is a placeholder implementation. In production, this would:\n`;
|
||||
output += `1. Create cost function from Hamiltonian expectation value\n`;
|
||||
output += `2. Use gradient-based or gradient-free optimization\n`;
|
||||
output += `3. Return optimized parameters and minimum energy\n`;
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error in variational optimization:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error in variational optimization: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const quantumExecutionTools: Tool[] = [
|
||||
sampleQuantumCircuitTool,
|
||||
observeHamiltonianTool,
|
||||
getQuantumStateTool,
|
||||
runQuantumAlgorithmTool,
|
||||
variationalOptimizationTool
|
||||
];
|
||||
446
src/tools/hardware-tools.ts
Archivo normal
446
src/tools/hardware-tools.ts
Archivo normal
@@ -0,0 +1,446 @@
|
||||
/**
|
||||
* Hardware Backend Tools for MCP Server
|
||||
* Provides tools for managing quantum execution targets and hardware backends
|
||||
*/
|
||||
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { SetTargetSchema, QuantumBackends } from '../types/index.js';
|
||||
import { getPythonBridge } from '../bridge/python-bridge.js';
|
||||
import { Logger } from '../utils/logger.js';
|
||||
|
||||
const logger = new Logger('HardwareBackendTools');
|
||||
|
||||
/**
|
||||
* Tool for setting quantum execution target
|
||||
*/
|
||||
export const setQuantumTargetTool: Tool = {
|
||||
name: 'set_quantum_target',
|
||||
description: 'Set the quantum execution target (simulator or hardware backend)',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
target: {
|
||||
type: 'string',
|
||||
description: 'Quantum target name',
|
||||
enum: Object.keys(QuantumBackends)
|
||||
},
|
||||
configuration: {
|
||||
type: 'object',
|
||||
description: 'Target-specific configuration options',
|
||||
properties: {
|
||||
shots: { type: 'integer', minimum: 1, maximum: 100000 },
|
||||
optimization_level: { type: 'integer', minimum: 0, maximum: 3 },
|
||||
api_key: { type: 'string', description: 'API key for hardware providers' },
|
||||
url: { type: 'string', description: 'Custom endpoint URL' },
|
||||
device: { type: 'string', description: 'Specific device name' },
|
||||
noise_model: { type: 'string', description: 'Noise model for simulation' },
|
||||
error_mitigation: { type: 'boolean', description: 'Enable error mitigation' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['target']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for listing available quantum backends
|
||||
*/
|
||||
export const listQuantumBackendsTool: Tool = {
|
||||
name: 'list_quantum_backends',
|
||||
description: 'List all available quantum backends and their capabilities',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
category: {
|
||||
type: 'string',
|
||||
enum: ['all', 'simulators', 'hardware'],
|
||||
default: 'all',
|
||||
description: 'Filter backends by category'
|
||||
},
|
||||
detailed: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Include detailed information about each backend'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for getting platform information
|
||||
*/
|
||||
export const getPlatformInfoTool: Tool = {
|
||||
name: 'get_platform_info',
|
||||
description: 'Get information about the current quantum platform and available resources',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for testing backend connectivity
|
||||
*/
|
||||
export const testBackendConnectivityTool: Tool = {
|
||||
name: 'test_backend_connectivity',
|
||||
description: 'Test connectivity to quantum hardware providers',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
backend: {
|
||||
type: 'string',
|
||||
description: 'Backend to test',
|
||||
enum: Object.keys(QuantumBackends)
|
||||
},
|
||||
credentials: {
|
||||
type: 'object',
|
||||
description: 'Credentials for the backend',
|
||||
properties: {
|
||||
api_key: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
username: { type: 'string' },
|
||||
password: { type: 'string' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['backend']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tool for GPU acceleration configuration
|
||||
*/
|
||||
export const configureGpuAccelerationTool: Tool = {
|
||||
name: 'configure_gpu_acceleration',
|
||||
description: 'Configure GPU acceleration for quantum simulations',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
enable: {
|
||||
type: 'boolean',
|
||||
description: 'Enable or disable GPU acceleration'
|
||||
},
|
||||
device_id: {
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
description: 'GPU device ID to use'
|
||||
},
|
||||
memory_limit: {
|
||||
type: 'number',
|
||||
description: 'GPU memory limit in GB'
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
enum: ['qpp-gpu', 'density-matrix-gpu'],
|
||||
default: 'qpp-gpu',
|
||||
description: 'GPU-accelerated target'
|
||||
}
|
||||
},
|
||||
required: ['enable']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation functions
|
||||
*/
|
||||
|
||||
export async function handleSetQuantumTarget(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.setTarget(input.target, input.configuration);
|
||||
|
||||
if (response.success) {
|
||||
logger.info(`Set quantum target to: ${input.target}`);
|
||||
|
||||
let output = `Successfully set quantum target to: ${input.target}\n\n`;
|
||||
output += `Description: ${QuantumBackends[input.target as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.configuration) {
|
||||
output += `\nConfiguration:\n`;
|
||||
for (const [key, value] of Object.entries(input.configuration)) {
|
||||
if (key !== 'api_key') { // Don't log sensitive information
|
||||
output += ` ${key}: ${value}\n`;
|
||||
} else {
|
||||
output += ` ${key}: [REDACTED]\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to set quantum target');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error setting quantum target:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error setting quantum target: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleListQuantumBackends(input: any) {
|
||||
try {
|
||||
let output = `Available Quantum Backends:\n\n`;
|
||||
|
||||
const simulators = ['qpp-cpu', 'qpp-gpu', 'density-matrix-cpu', 'tensor-network'];
|
||||
const hardware = ['ionq', 'quantinuum', 'quantum_machines', 'infleqtion', 'iqm', 'oqc', 'pasqal'];
|
||||
|
||||
if (input.category === 'all' || input.category === 'simulators') {
|
||||
output += `🖥️ Simulators:\n`;
|
||||
for (const backend of simulators) {
|
||||
if (backend in QuantumBackends) {
|
||||
output += ` • ${backend}: ${QuantumBackends[backend as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.detailed) {
|
||||
output += ` - Local execution\n`;
|
||||
output += ` - GPU support: ${backend.includes('gpu') ? 'Yes' : 'No'}\n`;
|
||||
output += ` - Max qubits: ${backend.includes('tensor') ? '40+' : '32'}\n`;
|
||||
output += `\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
output += `\n`;
|
||||
}
|
||||
|
||||
if (input.category === 'all' || input.category === 'hardware') {
|
||||
output += `🔬 Hardware Providers:\n`;
|
||||
for (const backend of hardware) {
|
||||
if (backend in QuantumBackends) {
|
||||
output += ` • ${backend}: ${QuantumBackends[backend as keyof typeof QuantumBackends]}\n`;
|
||||
|
||||
if (input.detailed) {
|
||||
output += ` - Remote execution\n`;
|
||||
output += ` - Authentication required\n`;
|
||||
output += ` - Variable queue times\n`;
|
||||
output += `\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output += `\nTo set a target, use: set_quantum_target\n`;
|
||||
output += `For GPU acceleration, ensure CUDA is installed and use GPU-enabled targets.\n`;
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error listing quantum backends:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error listing quantum backends: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleGetPlatformInfo(input: any) {
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
|
||||
const response = await bridge.getPlatformInfo();
|
||||
|
||||
if (response.success) {
|
||||
const result = response.result || {};
|
||||
|
||||
let output = `Quantum Platform Information:\n\n`;
|
||||
output += `Platform Name: ${result.platform_name || 'Unknown'}\n`;
|
||||
output += `Number of QPUs: ${result.num_qpus || 'Unknown'}\n`;
|
||||
output += `Is Simulator: ${result.is_simulator !== undefined ? result.is_simulator : 'Unknown'}\n`;
|
||||
output += `Is Remote: ${result.is_remote !== undefined ? result.is_remote : 'Unknown'}\n`;
|
||||
|
||||
// Add system information
|
||||
output += `\nSystem Information:\n`;
|
||||
output += `Node.js Version: ${process.version}\n`;
|
||||
output += `Platform: ${process.platform}\n`;
|
||||
output += `Architecture: ${process.arch}\n`;
|
||||
|
||||
// GPU information (if available)
|
||||
const cudaDevice = process.env.CUDA_VISIBLE_DEVICES;
|
||||
if (cudaDevice) {
|
||||
output += `CUDA Visible Devices: ${cudaDevice}\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to get platform information');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error getting platform information:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error getting platform information: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleTestBackendConnectivity(input: any) {
|
||||
try {
|
||||
const backend = input.backend;
|
||||
|
||||
let output = `Testing connectivity to ${backend}...\n\n`;
|
||||
|
||||
// Check if it's a simulator (always available)
|
||||
const simulators = ['qpp-cpu', 'qpp-gpu', 'density-matrix-cpu', 'tensor-network'];
|
||||
|
||||
if (simulators.includes(backend)) {
|
||||
output += `✅ ${backend} is available (local simulator)\n`;
|
||||
|
||||
if (backend.includes('gpu')) {
|
||||
const cudaDevice = process.env.CUDA_VISIBLE_DEVICES;
|
||||
if (cudaDevice) {
|
||||
output += `✅ CUDA device available: ${cudaDevice}\n`;
|
||||
} else {
|
||||
output += `⚠️ CUDA_VISIBLE_DEVICES not set, using default GPU\n`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Hardware backend - check credentials
|
||||
output += `🔗 ${backend} is a hardware provider\n`;
|
||||
|
||||
if (input.credentials?.api_key) {
|
||||
output += `✅ API key provided\n`;
|
||||
} else {
|
||||
output += `❌ API key required for ${backend}\n`;
|
||||
}
|
||||
|
||||
if (input.credentials?.url) {
|
||||
output += `✅ Custom URL provided: ${input.credentials.url}\n`;
|
||||
}
|
||||
|
||||
output += `\nNote: Actual connectivity testing requires valid credentials and active connection.\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error testing backend connectivity:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error testing backend connectivity: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleConfigureGpuAcceleration(input: any) {
|
||||
try {
|
||||
let output = `GPU Acceleration Configuration:\n\n`;
|
||||
|
||||
if (input.enable) {
|
||||
output += `✅ Enabling GPU acceleration\n`;
|
||||
output += `Target: ${input.target || 'qpp-gpu'}\n`;
|
||||
|
||||
if (input.device_id !== undefined) {
|
||||
output += `GPU Device ID: ${input.device_id}\n`;
|
||||
// Update environment variable
|
||||
process.env.CUDA_VISIBLE_DEVICES = input.device_id.toString();
|
||||
}
|
||||
|
||||
if (input.memory_limit) {
|
||||
output += `Memory Limit: ${input.memory_limit} GB\n`;
|
||||
}
|
||||
|
||||
// Attempt to set GPU target
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
const response = await bridge.setTarget(input.target || 'qpp-gpu');
|
||||
|
||||
if (response.success) {
|
||||
output += `✅ Successfully configured GPU target\n`;
|
||||
} else {
|
||||
output += `❌ Failed to set GPU target: ${response.error}\n`;
|
||||
}
|
||||
} catch (error) {
|
||||
output += `❌ Error setting GPU target: ${error}\n`;
|
||||
}
|
||||
|
||||
output += `\nNote: Ensure NVIDIA drivers and CUDA toolkit are installed for GPU acceleration.\n`;
|
||||
} else {
|
||||
output += `❌ Disabling GPU acceleration\n`;
|
||||
output += `Falling back to CPU simulation\n`;
|
||||
|
||||
try {
|
||||
const bridge = getPythonBridge();
|
||||
await bridge.setTarget('qpp-cpu');
|
||||
output += `✅ Set target to CPU simulator\n`;
|
||||
} catch (error) {
|
||||
output += `❌ Error setting CPU target: ${error}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: output
|
||||
}
|
||||
]
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error configuring GPU acceleration:', error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Error configuring GPU acceleration: ${error instanceof Error ? error.message : String(error)}`
|
||||
}
|
||||
],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export all tools
|
||||
export const hardwareBackendTools: Tool[] = [
|
||||
setQuantumTargetTool,
|
||||
listQuantumBackendsTool,
|
||||
getPlatformInfoTool,
|
||||
testBackendConnectivityTool,
|
||||
configureGpuAccelerationTool
|
||||
];
|
||||
Referencia en una nueva incidencia
Block a user