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

This commit is contained in:
2026-07-01 16:20:51 +03:00
parent 5801947c0d
commit c776326204
10 changed files with 258 additions and 258 deletions
+36 -11
View File
@@ -1,14 +1,39 @@
from langgraph.graph import StateGraph
from src.nodes import generate_response
from typing import Dict, Any
"""
Graph definition for the LangGraph workflow.
def build_graph() -> StateGraph:
The graph consists of two nodes:
1. ReflectNode generates a reflection of the user input.
2. RewriteNode rewrites the reflection into a more formal style.
The graph starts at the reflect node, then proceeds to the rewrite node,
and finishes with the rewritten output.
"""
from langgraph.graph import StateGraph
from src.nodes.reflect import ReflectNode
from src.nodes.rewrite import RewriteNode
def build_graph():
"""
Builds a simple StateGraph with a single node that echoes user input.
Build and compile the LangGraph graph.
Returns
-------
langgraph.graph.Graph
The compiled graph ready for invocation.
"""
graph = StateGraph()
# Add the echo node
graph.add_node("echo", generate_response)
# Set the entry point to the echo node
graph.set_entry_point("echo")
return graph
builder = StateGraph()
builder.add_node("reflect", ReflectNode.run)
builder.add_node("rewrite", RewriteNode.run)
# Entry point is the reflect node
builder.set_entry_point("reflect")
# Define the flow: reflect -> rewrite
builder.add_edge("reflect", "rewrite")
# Finish at the rewrite node
builder.set_finish("rewrite")
return builder.compile()
+9 -91
View File
@@ -1,100 +1,18 @@
#!/usr/bin/env python3
"""
Graph Reflection and Refinement Demo with LangChain LLM Integration.
Entry point for running the LangGraph workflow.
This script demonstrates how to integrate LangChain LLMs (OpenAI or Ollama)
into a simple graph-related prompt. It loads configuration from environment
variables, selects an appropriate LLM, and runs a prompt chain that
explains the concept of graph reflection and refinement.
Requirements:
- langchain
- langchain-openai
- langchain-ollama
- python-dotenv
- openai
This script demonstrates how to invoke the graph with a sample input.
"""
import os
from pathlib import Path
# Load environment variables from a .env file if present
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
# dotenv is optional; if not installed, environment variables must be set manually
pass
# Import LangChain components
try:
from langchain import PromptTemplate, LLMChain
from langchain_openai import OpenAI
from langchain_ollama import Ollama
except ImportError as exc:
raise ImportError(
"Required LangChain packages are missing. "
"Please install them via 'pip install -r requirements.txt'."
) from exc
from src.graph import build_graph
def get_llm() -> "BaseLLM":
"""
Instantiate an LLM based on available environment variables.
Returns:
An instance of a LangChain LLM (OpenAI or Ollama).
Raises:
RuntimeError: If neither OpenAI nor Ollama configuration is found.
"""
# Prefer OpenAI if API key is available
openai_key = os.getenv("OPENAI_API_KEY")
if openai_key:
return OpenAI(
model_name=os.getenv("OPENAI_MODEL", "gpt-3.5-turbo"),
temperature=float(os.getenv("OPENAI_TEMPERATURE", "0.7")),
openai_api_key=openai_key,
)
# Fallback to Ollama if host is configured
ollama_host = os.getenv("OLLAMA_HOST")
if ollama_host:
return Ollama(
model=os.getenv("OLLAMA_MODEL", "llama2"),
temperature=float(os.getenv("OLLAMA_TEMPERATURE", "0.7")),
base_url=ollama_host,
)
raise RuntimeError(
"No LLM configuration found. Set either OPENAI_API_KEY or OLLAMA_HOST "
"in your environment."
)
def main() -> None:
"""
Main entry point: builds a prompt chain and prints the LLM response.
"""
llm = get_llm()
# Simple prompt template explaining graph reflection and refinement
prompt = PromptTemplate(
input_variables=[],
template=(
"You are an expert in graph theory. "
"Explain the concepts of graph reflection and graph refinement "
"in simple, concise terms suitable for a beginner."
),
)
chain = LLMChain(llm=llm, prompt=prompt)
# Run the chain and print the result
response = chain.run()
print("\n=== LLM Response ===\n")
print(response)
def main():
graph = build_graph()
# Sample input
input_state = {"input": "Hello world"}
result = graph.invoke(input_state)
print("Graph output:", result)
if __name__ == "__main__":
+40
View File
@@ -0,0 +1,40 @@
"""
Reflect node for LangGraph.
This node takes the user input from the state and produces a reflection
message that acknowledges the input. The output is a dictionary containing
the key 'reflection'.
"""
from langgraph.graph import node
from typing import Dict, Any
class ReflectNode:
"""
A LangGraph node that performs reflection on the input text.
"""
@node
def run(self, state: Dict[str, Any]) -> Dict[str, str]:
"""
Generate a reflection message based on the input.
Parameters
----------
state : dict
The current state of the graph. Expected to contain an 'input'
key with the user-provided text.
Returns
-------
dict
A dictionary with a single key 'reflection' containing the
reflection message.
"""
input_text = state.get("input", "")
reflection = (
f"I see that you said: '{input_text}'. "
"Let's reflect on that."
)
return {"reflection": reflection}
+38
View File
@@ -0,0 +1,38 @@
"""
Rewrite node for LangGraph.
This node takes the reflection produced by the ReflectNode and rewrites
it to a more formal style. The output is a dictionary containing
the key 'rewritten'.
"""
from langgraph.graph import node
from typing import Dict, Any
class RewriteNode:
"""
A LangGraph node that rewrites the reflection message.
"""
@node
def run(self, state: Dict[str, Any]) -> Dict[str, str]:
"""
Rewrite the reflection message.
Parameters
----------
state : dict
The current state of the graph. Expected to contain a 'reflection'
key with the message produced by the ReflectNode.
Returns
-------
dict
A dictionary with a single key 'rewritten' containing the
rewritten message.
"""
reflection = state.get("reflection", "")
# Simple rewrite: replace "I see" with "I notice"
rewritten = reflection.replace("I see", "I notice")
return {"rewritten": rewritten}