Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ For tracking and metrics, DeepNext integrates with LangSmith. Set up your creden

[See configuration details](https://stxnext.github.io/deep-next/configuration.html)

## LangGraph Studio
You can view Deep Next workflow graph in LangGraph Studio, to do this invoke in a console:
```
langgraph dev
```
It will redirect you to [LangSmith UI](https://smith.langchain.com/), log in and you can see the graph.

## Roadmap

- **May 2025**: First public release (for registered STX Next employees)
Expand Down
7 changes: 7 additions & 0 deletions langgraph.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": ["."],
"graphs": {
"agent": "./libs/core/deep_next/core/graph.py:deep_next_graph_studio"
},
"env": ".env"
}
16 changes: 11 additions & 5 deletions libs/core/deep_next/core/base_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,32 @@ def __init__(
self._setup_fn = setup_fn
self._teardown_fn = teardown_fn

self.__dict__.update(self._compiled_graph.__dict__)
self.__dict__.update(self._compiled_graph.__dict__) # ?

def __getattr__(self, name):
return getattr(self._compiled_graph, name)

def invoke(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
"""Run setup -> original invoke -> teardown."""
state = kwargs.get("input", args[0])

self._setup_fn(state)

try:
return self._compiled_graph.invoke(*args, **kwargs)
finally:
self._teardown_fn(state)

def copy(self, update=None):
"""Let Studio clone the real compiled graph."""
return self._compiled_graph.copy(update)


class BaseGraph(StateGraph, ABC):
def __init__(
self,
state_cls: type[BaseModel | BaseModel],
state_cls: type[BaseModel],
config_schema: type | None = None, # ADD THIS
):
super().__init__(state_cls)
super().__init__(state_cls, config_schema=config_schema)
self.setup_fn = lambda _: None
self.teardown_fn = lambda _: None
self._build()
Expand Down
22 changes: 20 additions & 2 deletions libs/core/deep_next/core/graph.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import textwrap
from pathlib import Path
from typing import Literal
from typing import Literal, TypedDict

from deep_next.common.common import prepare_issue_statement
from deep_next.core.base_graph import BaseGraph
Expand All @@ -12,11 +12,18 @@
gather_project_knowledge_graph,
)
from deep_next.core.steps.implement.graph import implement_graph
from langchain_core.runnables import RunnableConfig
from langgraph.graph import END, START
from loguru import logger
from pydantic import BaseModel, Field


class DeepNextGraphConfig(TypedDict):
root: str
problem_statement: str
hints: str


class DeepNextResult(BaseModel):
"""Response model for DeepNext."""

Expand Down Expand Up @@ -159,7 +166,7 @@ class DeepNextGraph(BaseGraph):
"""Main graph for DeepNext."""

def __init__(self):
super().__init__(_State)
super().__init__(_State, config_schema=DeepNextGraphConfig)

def _build(self):
self.add_quick_node(_Node.gather_project_knowledge)
Expand Down Expand Up @@ -236,3 +243,14 @@ def __call__(

if __name__ == "__main__":
print(f"Saved to: {deep_next_graph.visualize(subgraph_depth=2)}")


def deep_next_graph_studio(config: RunnableConfig):
conf = config.get("configurable", {})

config["configurable"]["thread_id"] = conf.get("thread_id", "default-thread")
graph = DeepNextGraph()
return graph.compile()


__all__ = ["deep_next_graph_studio"]
Loading