Metaviz-Pro/Website_content_generation
4
1from langgraph.graph import END
2from fastapi import FastAPI, HTTPException
3from fastapi.responses import JSONResponse
4from fastapi.middleware.cors import CORSMiddleware
5from pydantic import BaseModel
6from typing import Dict, List, Any
7from langgraph.graph import StateGraph
8from service import research_task, seo_optimization_task, content_writing_task, refine_content, evaluate_content_quality, feedback_improvement, meeting_insights, upload_file
9from langchain_google_genai import ChatGoogleGenerativeAI
10from service import system_prompt
11app = FastAPI()
12app.add_middleware(
13 CORSMiddleware,
14 allow_origins=["*"], # Change this to specific origins if needed
15 allow_credentials=True,
16 allow_methods=["*"], # Allow all methods (GET, POST, PUT, DELETE, etc.)
17 allow_headers=["*"], # Allow all headers
18)
19
20llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
21class ContentState(Dict):
22 idea: str
23 company_name: str
24 services: Dict[str, List[str]] # Main services with their sub-services
25 service_area: Dict[str, Dict[str, str]] # Each area has multiple sub-service pages
26 research_data: str
27 seo_optimization: str
28 home_page: str
29 about_us_page: str
30 service_page: str
31 individual_service_page: Dict[str, str] # Single service pages
32 service_area_page: Dict[str, Dict[str, str]] # Each area with its sub-services
33 quality_score: int
34 feedback: str
35 content: str
36 data: str
37 text:str
38 meeting_point:str
39 file_path:str
40workflow = StateGraph(ContentState)
41
42# ✅ Define Workflow Steps
43workflow.add_node("research_step", research_task)
44workflow.add_node("seo_step", seo_optimization_task)
45workflow.add_node("writing_step", content_writing_task)
46workflow.add_node("refine_content", refine_content)
47workflow.add_node("evaluate_content_quality", evaluate_content_quality)
48workflow.add_node("feedback_improvement", feedback_improvement) # Node for quality rework
49workflow.add_node("human_review", lambda state: state) # Human-in-the-loop review
50workflow.add_node("meeting_insights",meeting_insights)
51workflow.add_node("upload_file",upload_file)
52# ✅ Define Transitions
53workflow.set_entry_point("research_step")
54workflow.set_entry_point("upload_file")
55workflow.add_edge("upload_file", "meeting_insights")
56workflow.add_edge("research_step", "seo_step")
57workflow.add_edge("seo_step", "writing_step")
58workflow.add_edge("meeting_insights", "writing_step")
59workflow.add_edge("writing_step", "refine_content")
60workflow.add_edge("refine_content", "evaluate_content_quality")
61
62# Conditional Flow for Quality Check & Human Review
63workflow.add_conditional_edges(
64 "evaluate_content_quality",
65 lambda state: "feedback_improvement" if state["quality_score"] <= 7 else "human_review",
66 {
67 "feedback_improvement": "feedback_improvement",
68 "human_review": "human_review"
69 }
70)
71
72# ✅ Add Loopback from feedback_improvement to refine_content
73workflow.add_edge("feedback_improvement", "evaluate_content_quality")
74
75# ✅ Add Human-in-the-loop approval before finalization
76workflow.add_edge("human_review", END)
77
78# ✅ Compile the Graph
79content_graph = workflow.compile()
80class RequestModel(BaseModel):
81 idea: str
82 company_name: str
83 services: Dict[str, List[str]]
84 service_area: List[str]
85class UpdateRequest(BaseModel):
86 page_key: List[str]
87 user_query: str
88
89def generate_content(data): # Remove @app.post to make it an importable function
90 state = content_graph.invoke({
91 "idea": data["idea"],
92 "company_name": data["company_name"],
93 "services": data["services"],
94 "service_area": data["service_area"],
95 "quality_score": 0,
96 "file_path": data["file_path"]
97 })
98
99 response = {
100 "home_page": state.get("home_page", ""),
101 "about_us_page": state.get("about_us_page", ""),
102 "service_page": state.get("service_page", ""),
103 "individual_service_page": state.get("individual_service_page", {}),
104 "service_area_page": state.get("service_area_page", {})
105 }
106
107 return response # Return dictionary instead of JSONResponse
108@app.post("/generate-content/")
109def generate_content_endpoint(request: RequestModel):
110 """
111 API endpoint to generate website content based on user input.
112 """
113 data = request.dict()
114
115 response = generate_content(data)
116
117 return JSONResponse(content=response)
118
119
120@app.put("/update-page/")
121def update_page(state: dict, user_query: str):
122 """
123 Updates the selected page content based on user feedback.
124 """
125 current_content = state.get("page_content", "")
126
127 # Define the prompt for updating the content
128 prompt = f"""
129 You are a professional content editor. Modify the content strictly according to the user request below.
130
131 ### **Rules for Modification**
132 - Apply the requested changes **EXACTLY as specified** in the user request.
133 - **Return the entire content** with only the requested modifications applied.
134 - **DO NOT return only the changed section**—always return the full content with modifications integrated.
135 - **DO NOT rephrase or modify anything that is not explicitly requested to change.**
136 - Ensure the modified content reads naturally and maintains professional quality.
137 - **DO NOT include explanations, formatting hints, or extra commentary—only return the final updated content.**
138
139 ### **User Request:**
140 {user_query}
141
142 ### **Original Content:**
143 {current_content}
144
145 ### **Updated Content (Return Full Updated Version Below):**
146 """
147
148 # Call Gemini to process the update
149 updated_content = llm.invoke([
150 {"role": "system", "content": system_prompt},
151 {"role": "user", "content": prompt}
152 ]).content.strip()
153
154 # Ensure the modified content is updated correctly
155 return {"page_content": updated_content}
156
157
158 