First working implementation of the program
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
import os
|
||||
from pydantic import BaseModel, Field as PydanticField # Alias it to avoid conflicts
|
||||
from crewai.tools import tool
|
||||
from typing import List, Dict, Any
|
||||
from shared_config import verbose, logger
|
||||
from crewai import Agent, Task, Crew, Process, LLM, TaskOutput, TaskOutput
|
||||
from crewai.tools import tool
|
||||
from langchain_community.tools import DuckDuckGoSearchRun
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
###########################################################################################
|
||||
#Define a callback function to log CrewAI step task
|
||||
###########################################################################################
|
||||
def log_task_to_file(output:TaskOutput):
|
||||
"""Callback function to append task details into the log file."""
|
||||
|
||||
formatted_str = f"""
|
||||
{'\n'}CrewAI Task Info
|
||||
{"=" * 50}
|
||||
Timestamp: {datetime.now()}
|
||||
Task Description: {output.description}
|
||||
Agent Assigned: {output.agent}
|
||||
{"-" * 30}
|
||||
Raw Output:{'\n'}
|
||||
{output.raw}{'\n'}
|
||||
{"=" * 50}
|
||||
"""
|
||||
logger.info(formatted_str)
|
||||
|
||||
def create_crew(config):
|
||||
|
||||
# ==========================================
|
||||
# 1. DEFINE CUSTOM TOOLS & OUTPUT SCHEMAS
|
||||
# ==========================================
|
||||
|
||||
# Simple search tool for the Research Agent
|
||||
@tool("web_search")
|
||||
def web_search_tool(query: str) -> str:
|
||||
"""Search the web for current events, news, or factual information."""
|
||||
ddg = DuckDuckGoSearchRun()
|
||||
return ddg.invoke(query)
|
||||
|
||||
|
||||
|
||||
class ResearchEvidence(BaseModel):
|
||||
source_url: str = PydanticField(..., description="The source URL of the evidence.")
|
||||
claim: str = PydanticField(..., description="The factual finding or data point.")
|
||||
context: str = PydanticField(..., description="The context or time frame of this data point.")
|
||||
|
||||
class ResearchOutputSchema(BaseModel):
|
||||
competitors: List[Dict[str, Any]] = PydanticField(..., description="List of competitors with pricing, features, and target audience.")
|
||||
market_trends: List[str] = PydanticField(..., description="Key macro trends observed.")
|
||||
evidence_citations: List[ResearchEvidence] = PydanticField(..., description="Valid source citations for facts collected.")
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
#Create llm instance
|
||||
# ---------------------------------------------------------
|
||||
if config.provider == "OpenAI":
|
||||
llm = LLM(
|
||||
model=config.model,
|
||||
api_key=os.getenv("OPENAI_API_KEY"),
|
||||
temperature=config.temperature,
|
||||
max_completion_tokens=config.max_tokens,
|
||||
)
|
||||
else:
|
||||
llm = LLM(
|
||||
model=f"ollama/{config.model}",
|
||||
api_key="ollama",
|
||||
base_url="http://localhost:11434",
|
||||
temperature=config.temperature
|
||||
)
|
||||
|
||||
logger.info(f"""LLM Model: {config.model}, Provider: {config.provider}, Temperature: {config.temperature}""")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 1. Agent Definitions
|
||||
# ---------------------------------------------------------
|
||||
|
||||
# 1. Orchestrator & Documenter (Manager)
|
||||
head_planner = Agent(
|
||||
role='Head Planner and Orchestrator',
|
||||
goal="Synthesize intermediary outputs and assemble the final master GTM document.",
|
||||
backstory="A precise compiler and documentarian...",
|
||||
#goal='Orchestrate the GTM workflow, delegate tasks to specialized agents, and synthesize all insights into a flawless final GTM document.',
|
||||
#backstory='You are a Principal Operations Strategy Director. You excel at managing cross-functional teams, ensuring strict alignment, and formatting messy raw data into executive-ready corporate documentation.',
|
||||
allow_delegation=False,
|
||||
verbose=verbose,
|
||||
llm=llm
|
||||
)
|
||||
|
||||
# 2. researcher
|
||||
researcher_agent = Agent(
|
||||
role="Market Research Specialist",
|
||||
goal="Gather raw competitive intelligence, target audience signals, and pricing tiers with structural citations.",
|
||||
backstory="An elite OSINT researcher who tracks digital signals. You ignore marketing fluff and extract verifiable numbers, product capabilities, and structural URLs.",
|
||||
#role='Research Agent',
|
||||
#goal='Gather comprehensive market data, identify industry trends, and map out the competitive landscape.',
|
||||
#backstory='You are an elite Market Research Analyst. You are an expert at mining deep web data, extracting customer pain points, and finding precise statistical facts from modern industry reports.',
|
||||
verbose=verbose,
|
||||
tools=[web_search_tool],
|
||||
use_system_prompt=False,
|
||||
llm=llm
|
||||
)
|
||||
|
||||
# 3. analyst
|
||||
analyst_agent = Agent(
|
||||
role="Strategic Business Analyst",
|
||||
goal="Transform unstructured research data into rigorous market models, SWOT matrixes, and 4P/7P frameworks.",
|
||||
backstory="A former MBB consultant who specializes in corporate strategy. You find patterns in chaotic data, flag market gaps, and synthesize pricing elasticities.",
|
||||
#role='Analyst Agent',
|
||||
#goal='Synthesize raw market data into structured frameworks like SWOT, 4P, 7P, and target user personas.',
|
||||
#backstory='You are a data-driven Strategic Analyst. You look past surface-level facts to find underlying market gaps, evaluate competitive positioning, and model risks.',
|
||||
verbose=verbose,
|
||||
llm=llm
|
||||
)
|
||||
|
||||
# 4. strategist
|
||||
strategist_agent = Agent(
|
||||
role="Go-To-Market (GTM) Strategist",
|
||||
goal="Draft the final actionable GTM blueprint including ICP maps, messaging layers, and launch milestone phases.",
|
||||
backstory="A legendary growth marketing executive. You turn raw analytical data into high-converting messaging matrixes, channel frameworks, and scalable product launch schedules.",
|
||||
#role='Strategy Agent',
|
||||
#goal='Formulate the actionable Go-To-Market blueprint, positioning, pricing strategies, and launch timelines.',
|
||||
#backstory='You are a veteran GTM Growth Strategist. You specialize in crafting commercial launch playbooks, positioning products uniquely against rivals, and designing user-acquisition loops.',
|
||||
verbose=verbose,
|
||||
llm=llm
|
||||
)
|
||||
# ---------------------------------------------------------
|
||||
# 2. Task Definitions
|
||||
# ---------------------------------------------------------
|
||||
|
||||
#Fetch User query from config
|
||||
query = config.user_query
|
||||
|
||||
# Task 1: Research Agent gathers raw intelligence
|
||||
research_task = Task(
|
||||
description=(
|
||||
"Search the web for the top 3-5 players in the target market: '{query}'. "
|
||||
"Extract pricing tiers, core feature modules, and target customer profiles. "
|
||||
"Every single metric or claim MUST have a URL source tracked inside the JSON structure. "
|
||||
"Do not fabricate any data and do not make assumptions. Only include verifiable facts using working URLs."
|
||||
"If you cannot find a specific metric, leave it blank and do not fabricate data."
|
||||
),
|
||||
expected_output="A structured JSON file matching the schema with validated competitive rows and strict citation tracking.",
|
||||
output_json=ResearchOutputSchema,
|
||||
agent=researcher_agent
|
||||
)
|
||||
|
||||
# Task 2: Analyst Agent creates comparative structures
|
||||
analysis_task = Task(
|
||||
description=(
|
||||
"Review the structured JSON output provided by the Research Agent. "
|
||||
"Construct a detailed markdown competitive landscape table and a pricing matrix. "
|
||||
"Perform a comprehensive SWOT, 4P, and 7P analysis based strictly on the evidence compiled."
|
||||
),
|
||||
expected_output="A deep-dive analytical report featuring clean markdown tables, a SWOT quadrant, and an exhaustive 4P/7P matrix analysis.",
|
||||
agent=analyst_agent
|
||||
)
|
||||
|
||||
# Task 3: Strategy Agent plans market entry
|
||||
strategy_task = Task(
|
||||
description=(
|
||||
"Take the analytical matrices and SWOT outputs to build a comprehensive GTM document. "
|
||||
"Define 2 distinct Ideal Customer Profiles (ICPs). Outline the core value proposition. "
|
||||
"Create a messaging framework (Hook, Problem, Solution) per ICP. "
|
||||
"Identify high-ROI acquisition channels and detail a 30-60-90 day milestone launch plan."
|
||||
),
|
||||
expected_output="An actionable, comprehensive market entry strategy blueprint divided into logical execution phases.",
|
||||
agent=strategist_agent
|
||||
)
|
||||
|
||||
# Task 4: Head Planner synthesizes, formats, and exports
|
||||
compilation_task = Task(
|
||||
description=(
|
||||
"Synthesize the outputs from the Research, Analyst, and Strategy agents into a seamless, high-caliber Master GTM Report. "
|
||||
"Include all research data tables, citations, SWOT/7P strategic matrices, and execution timelines. "
|
||||
"Include a title that cleary identifies the target market and a subtitle that highlights the core value proposition. "
|
||||
),
|
||||
expected_output="Final master GTM document.",
|
||||
context=[research_task, analysis_task, strategy_task],
|
||||
agent=head_planner
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 3. Crew Setup
|
||||
# ---------------------------------------------------------
|
||||
|
||||
crew= Crew(
|
||||
agents=[researcher_agent, analyst_agent, strategist_agent, head_planner],
|
||||
tasks=[research_task, analysis_task, strategy_task, compilation_task],
|
||||
process=Process.sequential, # Tasks execute in exact sequence
|
||||
#manager_agent=head_planner
|
||||
task_callback=log_task_to_file,
|
||||
verbose=verbose
|
||||
)
|
||||
|
||||
logger.info(f"Crew setup complete with {len(crew.agents)} agents and {len(crew.tasks)} tasks.")
|
||||
return crew
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
from langsmith import traceable
|
||||
from agent_workflows.crew_setup import create_crew
|
||||
from shared_config import AgenticAIConfig, logger
|
||||
from langsmith.integrations.otel import OtelSpanProcessor
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.instrumentation.crewai import CrewAIInstrumentor
|
||||
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
||||
|
||||
# Initialize the trace provider
|
||||
tracer_provider = TracerProvider()
|
||||
#trace.set_tracer_provider(tracer_provider)
|
||||
|
||||
# Add the LangSmith OTel processor
|
||||
tracer_provider.add_span_processor(OtelSpanProcessor())
|
||||
|
||||
# Instrument both CrewAI and OpenAI layers
|
||||
CrewAIInstrumentor().instrument(tracer_provider=tracer_provider)
|
||||
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
|
||||
|
||||
@traceable(name="Capstone_GTM Strategy Simulation", run_type="chain")
|
||||
def runAgenticWorkflow(config: AgenticAIConfig):
|
||||
"""
|
||||
Main Entry Point of Agentic AI Workflow
|
||||
"""
|
||||
logger.info("Agentic Workflow Started...")
|
||||
|
||||
crew = create_crew(config)
|
||||
|
||||
result = crew.kickoff(
|
||||
inputs={
|
||||
"query": config.user_query
|
||||
}
|
||||
)
|
||||
|
||||
config.response = str(result)
|
||||
return config
|
||||
Reference in New Issue
Block a user