feat: solution for 'Повторный экзамен: Граф с рефлексией и доработкой'

This commit is contained in:
2026-07-01 11:19:02 +03:00
parent 045dba9aef
commit cfe5d77a10
10 changed files with 309 additions and 94 deletions
+64 -18
View File
@@ -1,20 +1,66 @@
import * as langgraph from 'langgraph';
import { OpenAI } from 'langchain-openai';
import ReflectionNode from './nodes/reflectionNode.js';
import RewriteNode from './nodes/rewriteNode.js';
console.log('langgraph module loaded:', typeof langgraph);
console.log('OpenAI class loaded:', typeof OpenAI);
const llm = new OpenAI({
apiKey: process.env.OPENAI_API_KEY || '',
modelName: 'gpt-3.5-turbo',
});
(async () => {
const prompt = 'Hello, world!';
try {
const response = await llm.invoke(prompt);
console.log('LLM response:', response);
} catch (error) {
console.error('Error invoking LLM:', error);
/**
* Simple directed graph implementation that supports reflection and rewrite nodes.
*/
class Graph {
constructor() {
/** @type {Object.<string, Object>} */
this.nodes = {};
/** @type {Array<{from: string, to: string}>} */
this.edges = [];
}
})();
/**
* Adds a node to the graph.
* @param {Object} node - Node instance (must have id and type).
*/
addNode(node) {
if (!node || !node.id) {
throw new Error('Node must have an id.');
}
this.nodes[node.id] = node;
}
/**
* Adds a directed edge from one node to another.
* @param {string} fromId - Source node id.
* @param {string} toId - Destination node id.
*/
addEdge(fromId, toId) {
if (!this.nodes[fromId] || !this.nodes[toId]) {
throw new Error('Both nodes must exist before adding an edge.');
}
this.edges.push({ from: fromId, to: toId });
}
/**
* Evaluates the graph in topological order.
* @returns {Object.<string, *>} Mapping of node ids to their output values.
*/
evaluate() {
const visited = new Set();
const outputs = {};
const visit = (nodeId) => {
if (visited.has(nodeId)) return;
visited.add(nodeId);
// Find all incoming edges to this node
const incoming = this.edges.filter((e) => e.to === nodeId);
const inputValues = incoming.map((e) => outputs[e.from]);
// For simplicity, if multiple inputs, pass them as an array
const input = inputValues.length === 1 ? inputValues[0] : inputValues;
const node = this.nodes[nodeId];
outputs[nodeId] = node.process(input);
};
Object.keys(this.nodes).forEach(visit);
return outputs;
}
}
export { Graph, ReflectionNode, RewriteNode };