0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
import asyncio
|
|
import os
|
|
|
|
from langchain_openai import ChatOpenAI
|
|
from langgraph.graph import StateGraph
|
|
from pydantic import BaseModel
|
|
|
|
# Load the OpenAI API key from environment variable
|
|
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
|
|
|
|
|
# Define the data structure (state) passed between nodes in the graph
|
|
class ResearchState(BaseModel):
|
|
query: str # The original research query
|
|
raw_info: str = "" # Raw fetched or mocked information
|
|
summary: str = "" # Final summarized result
|
|
|
|
|
|
# Function to create and return the research agent graph
|
|
def get_research_agent(model="gpt-4o"):
|
|
# Initialize the OpenAI LLM with the specified model and API key
|
|
llm = ChatOpenAI(model=model, api_key=OPENAI_API_KEY)
|
|
|
|
# Create a stateful graph with ResearchState as the shared state type
|
|
graph = StateGraph(ResearchState)
|
|
|
|
# Node 1: Simulate a search function that populates raw_info
|
|
def search_info(state: ResearchState) -> ResearchState:
|
|
# TODO: Replace with real search API integration
|
|
mock_info = f"(Mock) According to recent sources, the latest trends in {state.query} include X, Y, Z."
|
|
return ResearchState(query=state.query, raw_info=mock_info)
|
|
|
|
# Node 2: Use the LLM to summarize the raw_info content
|
|
def summarize_info(state: ResearchState) -> ResearchState:
|
|
prompt = f"Summarize the following:\n{state.raw_info}"
|
|
response = llm.invoke(prompt) # Call the LLM to get the summary
|
|
return ResearchState(
|
|
query=state.query, raw_info=state.raw_info, summary=response.content
|
|
)
|
|
|
|
# Node 3: Format the final summary for output
|
|
def output_summary(state: ResearchState) -> ResearchState:
|
|
final_summary = f"Research summary for '{state.query}': {state.summary}"
|
|
return ResearchState(
|
|
query=state.query, raw_info=state.raw_info, summary=final_summary
|
|
)
|
|
|
|
# Add nodes to the graph
|
|
graph.add_node("search_info", search_info)
|
|
graph.add_node("summarize_info", summarize_info)
|
|
graph.add_node("output_summary", output_summary)
|
|
|
|
# Define the flow between nodes (edges)
|
|
graph.add_edge("search_info", "summarize_info")
|
|
graph.add_edge("summarize_info", "output_summary")
|
|
|
|
# Set the starting and ending points of the graph
|
|
graph.set_entry_point("search_info")
|
|
graph.set_finish_point("output_summary")
|
|
|
|
# Compile the graph into an executable app
|
|
return graph.compile()
|
|
|
|
|
|
# Function to run the research agent with a given query prompt
|
|
def run_research_agent(prompt):
|
|
# Get the compiled graph application
|
|
app = get_research_agent()
|
|
# Run the asynchronous invocation and get the result
|
|
result = asyncio.run(app.ainvoke(ResearchState(query=prompt)))
|
|
return result
|