LangChain#

Cognify supports unmodified LangChain programs. All you need to do is to register the entry function for Cognify to execute the workflow during optimization. The following is the LangChain code for the Math Problem Solver example:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

model = ChatOpenAI(model="gpt-4o", temperature=0, max_tokens=300)

interpreter_prompt = """
You are a math problem interpreter. Your task is to analyze the problem, identify key variables, and formulate the appropriate mathematical model or equation needed to solve it. Be concise and clear in your response.
"""

interpreter_template = ChatPromptTemplate.from_messages(
    [
        ("system", interpreter_prompt),
        ("human", "problem:\n{problem}\n"),
    ]
)

interpreter_agent = interpreter_template | model

solver_prompt = """
You are a math solver. Given a math problem, and a mathematical model for solving it, your task is to compute the solution and return the final answer. Be concise and clear in your response.
"""

solver_template = ChatPromptTemplate.from_messages(
    [
        ("system", solver_prompt),
        ("human", "problem:\n{problem}\n\nmath model:\n{math_model}\n"),
    ]
)

solver_agent = solver_template | model

import cognify

# Define Workflow
@cognify.register_workflow
def math_solver_workflow(workflow_input):
    math_model = interpreter_agent.invoke({"problem": workflow_input}).content
    answer = solver_agent.invoke({"problem": workflow_input, "math_model": math_model}).content
    return {"workflow_output": answer}

In LangChain, the Runnable class is the primary abstraction for executing a task. When initializing the optimizer, Cognify will automatically translate all runnables that are instantiated as global variables into a cognify.Model or cognify.StructuredModel.

Tip

Your chain must follow the following format: ChatPromptTemplate | ChatModel | (optional) OutputParser. This provides cognify.Model with all the information it needs to optimize your workflow. The chat prompt template must contain a system prompt and at least one input variable.

By default, Cognify will translate all runnables into valid optimization targets. For more fine-grained control over which Runnable should be targeted, you can manually wrap your chain with our cognify.RunnableModel class like so:

import cognify
...

solver_agent = solver_template | model | parser

# -- manually wrap the chain with RunnableModel --
solver_agent = cognify.RunnableModel("solver_agent", solver_agent)

from cognify.optimizer.registry import register_workflow
@cognify.register_workflow
def math_solver_workflow(workflow_input):
  math_model = interpreter_agent.invoke({"problem": workflow_input}).content

  # -- invocation remains the same --
  answer = solver_agent.invoke({"problem": workflow_input, "math_model": math_model}).content
  return {"workflow_output": answer}

If you prefer to define your modules using our cognify.Model interface but still want to utilize them with your existing LangChain infrastructure, you can wrap your cognify.Model with an as_runnable() call. This will convert your cognify.Model into a cognify.RunnableModel and follows the LangChain Runnable protocol.

import cognify
...

cognify_solver_agent = cognify.Model("solver_agent", ...)

# -- manually wrap the cognify model with `as_runnable()` --
solver_agent = cognify.as_runnable(cognify_solver_agent)

@cognify.register_workflow
def math_solver_workflow(workflow_input):
  math_model = interpreter_agent.invoke({"problem": workflow_input}).content

  # -- invocation remains the same --
  answer = solver_agent.invoke({"problem": workflow_input, "math_model": math_model}).content
  return {"workflow_output": answer}

Cognify is also compatible with LangGraph, a popular orchestration framework. It can be used to coordinate LangChain runnables, DSPy predictors, any other framework or even pure python. All you need to do to hook up your LangGraph code is use our decorator to register your invocation function.