diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc index 6f20a91decc0264d6f0f1e4995fa1e5e557b2ff8..8bfb4f4da4760c6ce19cf0a3e11471534e69b784 100644 Binary files a/__pycache__/main.cpython-312.pyc and b/__pycache__/main.cpython-312.pyc differ diff --git a/my_agent/__init__.py b/brainstroming_agent/__init__.py similarity index 100% rename from my_agent/__init__.py rename to brainstroming_agent/__init__.py diff --git a/my_agent/__pycache__/__init__.cpython-312.pyc b/brainstroming_agent/__pycache__/__init__.cpython-312.pyc similarity index 100% rename from my_agent/__pycache__/__init__.cpython-312.pyc rename to brainstroming_agent/__pycache__/__init__.cpython-312.pyc diff --git a/my_agent/__pycache__/agent.cpython-312.pyc b/brainstroming_agent/__pycache__/agent.cpython-312.pyc similarity index 65% rename from my_agent/__pycache__/agent.cpython-312.pyc rename to brainstroming_agent/__pycache__/agent.cpython-312.pyc index a05b091ccbee88845aecb6bcc02859b3ddb04951..f642a2e6d2a623a76fe93138314cc716eaa5b809 100644 Binary files a/my_agent/__pycache__/agent.cpython-312.pyc and b/brainstroming_agent/__pycache__/agent.cpython-312.pyc differ diff --git a/my_agent/agent.py b/brainstroming_agent/agent.py similarity index 97% rename from my_agent/agent.py rename to brainstroming_agent/agent.py index 5a9c2f0ae899c634abc7e87f88ca5f52d4dd38f8..b39dabe80ea75baae141be5f117f6de3b4f592ca 100644 --- a/my_agent/agent.py +++ b/brainstroming_agent/agent.py @@ -6,7 +6,7 @@ from langgraph.checkpoint.memory import MemorySaver memory = MemorySaver() -def build_graph(): +def brainstroming_graph(): builder = StateGraph(State) builder.add_node(caption_image) builder.add_node(retrieve) diff --git a/my_agent/utils/__init__.py b/brainstroming_agent/utils/__init__.py similarity index 100% rename from my_agent/utils/__init__.py rename to brainstroming_agent/utils/__init__.py diff --git a/my_agent/utils/__pycache__/__init__.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/__init__.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/__init__.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/__init__.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/business_interaction.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/business_interaction.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/business_interaction.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/business_interaction.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/check.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/check.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/check.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/check.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/data_loader.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/data_loader.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/data_loader.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/data_loader.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/initial_interaction.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/initial_interaction.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/initial_interaction.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/initial_interaction.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/models.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/models.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/models.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/models.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/models_loader.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/models_loader.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/models_loader.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/models_loader.cpython-312.pyc diff --git a/my_agent/utils/__pycache__/nodes.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/nodes.cpython-312.pyc similarity index 69% rename from my_agent/utils/__pycache__/nodes.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/nodes.cpython-312.pyc index d139761fec4e8686024a4bc632531959814dc30a..dde032be00d223f35c9a7a0d8f9e2dce74bad0d4 100644 Binary files a/my_agent/utils/__pycache__/nodes.cpython-312.pyc and b/brainstroming_agent/utils/__pycache__/nodes.cpython-312.pyc differ diff --git a/my_agent/utils/__pycache__/prompts.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/prompts.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/prompts.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/prompts.cpython-312.pyc diff --git a/brainstroming_agent/utils/__pycache__/state.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/state.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7deb9b12b8098b147ad02935c98a042b7d2ac248 Binary files /dev/null and b/brainstroming_agent/utils/__pycache__/state.cpython-312.pyc differ diff --git a/my_agent/utils/__pycache__/tools.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/tools.cpython-312.pyc similarity index 61% rename from my_agent/utils/__pycache__/tools.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/tools.cpython-312.pyc index c9ed2fea3755a9357ee3e104395259f1645d312f..2da1c3d58ecfd6f1b478b140186c9d41d7830b34 100644 Binary files a/my_agent/utils/__pycache__/tools.cpython-312.pyc and b/brainstroming_agent/utils/__pycache__/tools.cpython-312.pyc differ diff --git a/my_agent/utils/__pycache__/utils.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/utils.cpython-312.pyc similarity index 55% rename from my_agent/utils/__pycache__/utils.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/utils.cpython-312.pyc index b3bcfbd36ca7f4b04115bbebe2c6fe3e2e158621..a525e8e8947a8320aa00b8f9125f8cc06e887b08 100644 Binary files a/my_agent/utils/__pycache__/utils.cpython-312.pyc and b/brainstroming_agent/utils/__pycache__/utils.cpython-312.pyc differ diff --git a/my_agent/utils/__pycache__/validators.cpython-312.pyc b/brainstroming_agent/utils/__pycache__/validators.cpython-312.pyc similarity index 100% rename from my_agent/utils/__pycache__/validators.cpython-312.pyc rename to brainstroming_agent/utils/__pycache__/validators.cpython-312.pyc diff --git a/my_agent/utils/nodes.py b/brainstroming_agent/utils/nodes.py similarity index 92% rename from my_agent/utils/nodes.py rename to brainstroming_agent/utils/nodes.py index b09d13116542f071b56f53019186afa243497736..240b6facd667cc7c2efb03bb4750e886e62ac937 100644 --- a/my_agent/utils/nodes.py +++ b/brainstroming_agent/utils/nodes.py @@ -3,15 +3,15 @@ import ast from .state import State from .tools import retrieve_tool from langchain_core.messages import SystemMessage -from .models_loader import llm , ST -from .data_loader import load_influencer_data +from utils.models_loader import llm , ST +from utils.data_loader import load_influencer_data from groq import Groq import os from .prompts import image_captioning_prompt , initial_story_prompt , refined_story_prompt , brainstroming_prompt , final_story_prompt from langgraph.prebuilt import create_react_agent from pydantic import BaseModel , Field from langchain_core.tools import tool -from .validators import BrainstromTopicFormatter +from .state import BrainstromTopicFormatter @@ -113,15 +113,8 @@ def generate_brainstroming(state:State)-> State: template= brainstroming_prompt(state) messages = [SystemMessage(content=template)] - response = llm.bind_tools([BrainstromTopicFormatter]).invoke(messages) - print('The response is:',response) - if hasattr(response, 'tool_calls') and response.tool_calls: - response = response.tool_calls[0]['args'] - elif hasattr(response, 'content'): - response = response.content - else: - response = "No response" - + response = llm.with_structured_output(BrainstromTopicFormatter).invoke(messages) + response = response.model_dump() state.brainstroming_topics.append(response) print('The brainstroming topics are:',state.brainstroming_topics) # return State(messages="Story generated",topic=state.topic,brainstroming_topics=state.brainstroming_topics) diff --git a/my_agent/utils/prompts.py b/brainstroming_agent/utils/prompts.py similarity index 100% rename from my_agent/utils/prompts.py rename to brainstroming_agent/utils/prompts.py diff --git a/my_agent/utils/state.py b/brainstroming_agent/utils/state.py similarity index 54% rename from my_agent/utils/state.py rename to brainstroming_agent/utils/state.py index d4dcd2fa776666c6458dbce82d87bd3e1773efce..e3577553d2bc59ed2adefc2ad11e3491fc75ee90 100644 --- a/my_agent/utils/state.py +++ b/brainstroming_agent/utils/state.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, ConfigDict +from pydantic import BaseModel, ConfigDict , Field from typing import Optional import pandas as pd @@ -15,4 +15,11 @@ class State(BaseModel): latest_preferred_topics: Optional[list] = [] images: Optional[list[str]] = [] # Base64-encoded strings of images image_captions: Optional[list] = [] - model_config = ConfigDict(arbitrary_types_allowed=True) \ No newline at end of file + model_config = ConfigDict(arbitrary_types_allowed=True) + + +class BrainstromTopicFormatter(BaseModel): + topic1:str=Field(description="First brainstorming topic of the story") + topic2:str=Field(description="Second brainstorming topic of the story") + topic3:str=Field(description="Third brainstorming topic of the story") + topic4:str=Field(description="Fourth brainstorming topic of the story") diff --git a/my_agent/utils/tools.py b/brainstroming_agent/utils/tools.py similarity index 97% rename from my_agent/utils/tools.py rename to brainstroming_agent/utils/tools.py index 98ef4401355fb6b852ba52ebdd3d3b24c68b6c1b..46558178192eafec22de91473574e7406ff9f8a4 100644 --- a/my_agent/utils/tools.py +++ b/brainstroming_agent/utils/tools.py @@ -5,8 +5,8 @@ load_dotenv() import os import numpy as np from langchain_core.tools import tool -from .data_loader import load_influencer_data -from .models_loader import ST , llm +from utils.data_loader import load_influencer_data +from utils.models_loader import ST , llm from sklearn.metrics.pairwise import cosine_similarity import numpy as np from langchain_core.messages import SystemMessage diff --git a/my_agent/utils/utils.py b/brainstroming_agent/utils/utils.py similarity index 98% rename from my_agent/utils/utils.py rename to brainstroming_agent/utils/utils.py index f19cea364c5e8d900c9fda725bacc983cdee30e3..d2adcd02a2141b512972a99547563e87714a219b 100644 --- a/my_agent/utils/utils.py +++ b/brainstroming_agent/utils/utils.py @@ -1,7 +1,6 @@ from langchain_core.messages import SystemMessage -from .tools import StoryFormatter , retrieve_tool -from .models_loader import llm +from .tools import retrieve_tool import base64 from PIL import Image from io import BytesIO @@ -16,7 +15,7 @@ import ast import faiss import re import numpy as np -from .models_loader import ST +from utils.models_loader import ST , llm diff --git a/my_agent/utils/validators.py b/brainstroming_agent/utils/validators.py similarity index 100% rename from my_agent/utils/validators.py rename to brainstroming_agent/utils/validators.py diff --git a/business_interaction_agent/__init__.py b/business_interaction_agent/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/business_interaction_agent/__pycache__/__init__.cpython-312.pyc b/business_interaction_agent/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..730ea4d6877ac62ba75d25bdf1ca290b8ad00427 Binary files /dev/null and b/business_interaction_agent/__pycache__/__init__.cpython-312.pyc differ diff --git a/business_interaction_agent/__pycache__/agent.cpython-312.pyc b/business_interaction_agent/__pycache__/agent.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9eea963aac6216626554d9c725c778d68e65466 Binary files /dev/null and b/business_interaction_agent/__pycache__/agent.cpython-312.pyc differ diff --git a/my_agent/utils/business_interaction.py b/business_interaction_agent/agent.py similarity index 56% rename from my_agent/utils/business_interaction.py rename to business_interaction_agent/agent.py index fa60faddb24b4d8f7e5bfa084ce454e677661628..540bad8ee482c065ea86d0613546d9c590976f37 100644 --- a/my_agent/utils/business_interaction.py +++ b/business_interaction_agent/agent.py @@ -1,26 +1,44 @@ -import os from langchain_groq import ChatGroq from langgraph.graph import StateGraph, MessagesState, START, END from langgraph.checkpoint.memory import MemorySaver -from langchain_core.messages import SystemMessage, HumanMessage, AIMessage -from pydantic import BaseModel, ConfigDict, Field -from typing import Optional, List -from .models_loader import llm,ST -from .prompts import introduction_prompt , business_interaction_prompt, business_retrieval_prompt -from .tools import retrieve_tool from langgraph.prebuilt import create_react_agent -from .utils import manual_retrieval - +from .utils.state import State +# from .utils.nodes import business_interaction_node, cleanup_messages +from utils.models_loader import llm +from langchain_core.messages import SystemMessage +from .utils.prompts import business_retrieval_prompt +from .utils.utils import manual_retrieval +business_state = State() +# class BusinessInteractionChatbot: +# def __init__(self): +# self.messages = [] +# self.business_details = None +# self.react_agent = create_react_agent(model=llm, tools=[]) +# self.memory = MemorySaver() +# self.workflow = self._initialize_workflow() +# self.interact_agent = self.workflow.compile(checkpointer=self.memory) -# State model -class State(BaseModel): - interactions: Optional[list] = [] - model_config = ConfigDict(arbitrary_types_allowed=True) +# def _initialize_workflow(self): +# workflow = StateGraph(MessagesState) +# workflow.add_node("chatbot", lambda state: business_interaction_node( +# state, llm, self.react_agent, self.messages, self.business_details)) +# workflow.add_node("remove_message", lambda state: cleanup_messages(self.messages)) +# workflow.add_edge(START, "chatbot") +# workflow.add_edge("chatbot", "remove_message") +# workflow.add_edge("chatbot", END) +# return workflow -# Global business state (shared) -business_state = State() +# def chat(self, user_input: str, business_details: dict): +# self.business_details = business_details +# self.messages.append({"role": "user", "content": user_input}) +# config = {"configurable": {"thread_id": "2"}} +# response = self.interact_agent.invoke({"messages": self.messages}, config)['messages'][-1].content +# self.messages.append({"role": "assistant", "content": response}) +# business_state.interactions.append({'user': user_input, 'agent_response': response}) +# return response + class BusinessInteractionChatbot: def __init__(self): @@ -51,7 +69,7 @@ class BusinessInteractionChatbot: def _call_model(self, state): print('Entered into callmodel') retrievals = manual_retrieval(str([msg['content'] for msg in self.messages if msg['role'] == 'user']),self.business_details) - template = business_retrieval_prompt(str([msg['content'] for msg in self.messages if msg['role'] == 'user']),retrievals) + template = business_retrieval_prompt(str([msg['content'] for msg in self.messages if msg['role'] == 'user']),retrievals,str(self.business_details)) messages = [SystemMessage(content=template)] + state["messages"] backup_response = self.react_agent.invoke({'messages':messages})['messages'][-1] print('Backup response:',backup_response.content) @@ -68,4 +86,4 @@ class BusinessInteractionChatbot: self.messages.append({"role": "assistant", "content": response}) print('The message_history:',self.messages) business_state.interactions.append({'user': user_input, 'agent_response': response}) - return response + return response \ No newline at end of file diff --git a/business_interaction_agent/utils/__init__.py b/business_interaction_agent/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/business_interaction_agent/utils/__pycache__/__init__.cpython-312.pyc b/business_interaction_agent/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d4836bc25c9ca3c94e146e6dd8843bf041ddb67 Binary files /dev/null and b/business_interaction_agent/utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/business_interaction_agent/utils/__pycache__/nodes.cpython-312.pyc b/business_interaction_agent/utils/__pycache__/nodes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..416ea2d91ebc37a343ffc217bd32e96fc5af73cd Binary files /dev/null and b/business_interaction_agent/utils/__pycache__/nodes.cpython-312.pyc differ diff --git a/business_interaction_agent/utils/__pycache__/prompts.cpython-312.pyc b/business_interaction_agent/utils/__pycache__/prompts.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce705858c36f2369e4a6d60f7f51c680699012c1 Binary files /dev/null and b/business_interaction_agent/utils/__pycache__/prompts.cpython-312.pyc differ diff --git a/business_interaction_agent/utils/__pycache__/state.cpython-312.pyc b/business_interaction_agent/utils/__pycache__/state.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d532141281b994cb8448c3f3472da49e0e56a493 Binary files /dev/null and b/business_interaction_agent/utils/__pycache__/state.cpython-312.pyc differ diff --git a/business_interaction_agent/utils/__pycache__/utils.cpython-312.pyc b/business_interaction_agent/utils/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94eabf6b4d84cb2283ec83e3d4249bf6b67cdec0 Binary files /dev/null and b/business_interaction_agent/utils/__pycache__/utils.cpython-312.pyc differ diff --git a/business_interaction_agent/utils/nodes.py b/business_interaction_agent/utils/nodes.py new file mode 100644 index 0000000000000000000000000000000000000000..877236af22d9876146f15737b81593dd5454fa34 --- /dev/null +++ b/business_interaction_agent/utils/nodes.py @@ -0,0 +1,20 @@ +from langchain_core.messages import SystemMessage +from .prompts import business_retrieval_prompt +from .utils import manual_retrieval + +# This node generates a response using business context and retrieval +def business_interaction_node(state, llm, react_agent, messages, business_details): + print('Entered into callmodel') + user_inputs = str([msg['content'] for msg in messages if msg['role'] == 'user']) + retrievals = manual_retrieval(user_inputs, business_details) + template = business_retrieval_prompt(user_inputs, retrievals) + formatted_messages = [SystemMessage(content=template)] + state["messages"] + response = react_agent.invoke({'messages': formatted_messages})['messages'][-1] + print('Backup response:', response.content) + return {"messages": [response.content]} + +# Optional message cleanup node +def cleanup_messages(messages): + if len(messages) > 4: + return messages[2:] + return messages \ No newline at end of file diff --git a/business_interaction_agent/utils/prompts.py b/business_interaction_agent/utils/prompts.py new file mode 100644 index 0000000000000000000000000000000000000000..0558c9d16d1c3f0fd134d9b6b4f97ba18f36120b --- /dev/null +++ b/business_interaction_agent/utils/prompts.py @@ -0,0 +1,44 @@ +def business_retrieval_prompt(user_message, retrievals, business_details): + return f''' +You are a professional AI assistant helping users understand how influencers can support their business. You will be given: + +- A **user message** +- A list of **retrieved influencer data** +- The **business details** provided by the user + +Your job is to: +1. **First**, analyze the user message and decide if it is actually a business-related question or query that could be answered using influencer content. + - If the message is just a casual greeting like “Hi”, “Hello”, “How are you?”, or is not business-related (e.g., “Who are you?”, “Tell me a joke”), then **do NOT use the retrievals or business details**. Just respond to the user naturally and politely. + +2. **If the message is business-related**, proceed to: + a. Analyze the **business details** and check if the user message aligns with the type of business. + - If there is a mismatch (e.g., business is a restaurant but the user asks about clothing), politely **alert the user** about the mismatch. + - Still, go ahead and provide a helpful answer using relevant influencer data if available. + b. Analyze the influencer data and explain how each influencer might support the business based only on the retrieved content. + +--- USER MESSAGE --- +{user_message} + +--- BUSINESS DETAILS --- +{business_details} + +--- START OF RETRIEVALS --- +{retrievals} +--- END OF RETRIEVALS --- + +Rules: +- If the user message is **not relevant to influencer or business help**, politely respond in a general helpful way and ignore the retrievals and business details. +- If the message **is relevant**, then: + - First verify if the user’s business type matches the context of their message. + - If not, display a short alert to the user like: “Note: Your query seems to focus on [X], but your business is about [Y].” + - Then analyze the influencer stories: + - Identify which influencer content is relevant. + - Explain what they are promoting and how it might help the business. + - You **must mention influencer usernames** and only use what is in the retrievals. +- Do NOT invent or assume any information beyond what is explicitly provided in the retrievals and business details. + +Keep your response: +- Context-aware +- Grounded only in the given data +- Helpful, concise, and user-friendly +''' diff --git a/business_interaction_agent/utils/state.py b/business_interaction_agent/utils/state.py new file mode 100644 index 0000000000000000000000000000000000000000..d5e97dc251464e14d2abbccbf8d17eec53091392 --- /dev/null +++ b/business_interaction_agent/utils/state.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel, ConfigDict +from typing import Optional + +class State(BaseModel): + interactions: Optional[list] = [] + model_config = ConfigDict(arbitrary_types_allowed=True) \ No newline at end of file diff --git a/business_interaction_agent/utils/tools.py b/business_interaction_agent/utils/tools.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/business_interaction_agent/utils/utils.py b/business_interaction_agent/utils/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..57a1a4094c27e25eac7bb9006a65a66642d4d6cf --- /dev/null +++ b/business_interaction_agent/utils/utils.py @@ -0,0 +1,67 @@ +import pandas as pd +import faiss +import re +from utils.models_loader import ST +import numpy as np +import ast + + + +def manual_retrieval(messages, business_details): + # === Load CSV === + csv_path = 'extracted_data.csv' + df = pd.read_csv(csv_path) + + # === Parse stored embeddings === + df['embeddings'] = df['embeddings'].apply(lambda x: ast.literal_eval(x) if isinstance(x, str) else x) + embeddings = np.vstack(df['embeddings'].values).astype('float32') + + # === Build FAISS index === + dimension = embeddings.shape[1] + index = faiss.IndexFlatL2(dimension) + index.add(embeddings) + + # === Load SentenceTransformer model === + + # === Encode the query and search === + query_embedding = ST.encode(str(messages)+str(business_details)).reshape(1, -1).astype('float32') + top_k=3 + distances, indices = index.search(query_embedding, top_k) + + # === Function to extract sections 1 and 6 === + def extract_story_and_branding(full_story): + full_story = full_story.replace('**6. Visible Texts or Brandings**', '**6. Visible Texts or Brandings:**') + full_story = full_story.replace('**1. Story**', '**1. Story:**') + + pattern = ( + r"\*\*1\. Story:\*\*(.*?)(?=\*\*\d+\.\s)" + r".*?" + r"\*\*6\. Visible Texts or Brandings:\*\*(.*?)(?=\*\*\d+\.\s|$)" + ) + match = re.search(pattern, full_story, re.DOTALL) + if match: + story_section = match.group(1).strip() + branding_section = match.group(2).strip() + return f"Story:\n{story_section}\n\nVisible Texts or Brandings:\n{branding_section}" + else: + return "Requested sections not found." + + # === Format results === + outer_list = [] + for i, idx in enumerate(indices[0]): + res = { + 'rank': i + 1, + 'username': df.iloc[idx]['username'], + 'agentic_story': df.iloc[idx]['agentic_story'], + 'likesCount': df.iloc[idx]['likesCount'], + 'commentCount': df.iloc[idx]['commentCount'], + 'distance': distances[0][i] + } + + inner_list = [] + inner_list.append(f"[{res['rank']}]. The influencer name is: **{res['username']}** — Likes: **{res['likesCount']}**, Comments: **{res['commentCount']}**") + inner_list.append(f"The story of that particular video is:\n{extract_story_and_branding(res['agentic_story'])}") + inner_list.append(f"Distance: {res['distance']:.4f}") + outer_list.append(inner_list) + + return str(outer_list) \ No newline at end of file diff --git a/context_analysis_agent/__init__.py b/context_analysis_agent/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/context_analysis_agent/__pycache__/__init__.cpython-312.pyc b/context_analysis_agent/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe48d27356ea6453a69b409807fceb0f0e1d711f Binary files /dev/null and b/context_analysis_agent/__pycache__/__init__.cpython-312.pyc differ diff --git a/context_analysis_agent/__pycache__/agent.cpython-312.pyc b/context_analysis_agent/__pycache__/agent.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39e6fea9710f57efef7c3e4433b85d44e7ddc33e Binary files /dev/null and b/context_analysis_agent/__pycache__/agent.cpython-312.pyc differ diff --git a/my_agent/utils/initial_interaction.py b/context_analysis_agent/agent.py similarity index 54% rename from my_agent/utils/initial_interaction.py rename to context_analysis_agent/agent.py index 7784c473bed7890732d5bc548c8144a7cdd717b4..94f552f3f0a54efada1526ec21800dba173848a7 100644 --- a/my_agent/utils/initial_interaction.py +++ b/context_analysis_agent/agent.py @@ -1,27 +1,15 @@ -import os from langchain_groq import ChatGroq from langgraph.graph import StateGraph, MessagesState, START, END from langgraph.checkpoint.memory import MemorySaver -from langchain_core.messages import SystemMessage -from pydantic import BaseModel, ConfigDict, Field -from typing import Optional, List -from .models_loader import llm -from .prompts import introduction_prompt , details_extract_prompt -from .validators import DetailsFormatter +from .utils.state import State +from .utils.nodes import introduction_node, extract_business_details +from utils.models_loader import llm - -# State model -class State(BaseModel): - interactions: Optional[list] = [] - model_config = ConfigDict(arbitrary_types_allowed=True) - -# Global business state (shared) business_state = State() class IntroductionChatbot: def __init__(self): self.memory = MemorySaver() - # self.llm = ChatGroq(model_name="Gemma2-9b-It") self.llm = llm self.workflow = self._initialize_workflow() self.interact_agent = self.workflow.compile(checkpointer=self.memory) @@ -29,17 +17,11 @@ class IntroductionChatbot: def _initialize_workflow(self): workflow = StateGraph(MessagesState) - workflow.add_node("chatbot", self._call_model) + workflow.add_node("chatbot", lambda state: introduction_node(state, self.llm)) workflow.add_edge(START, "chatbot") workflow.add_edge("chatbot", END) return workflow - def _call_model(self, state): - template = introduction_prompt - messages = [SystemMessage(content=template)] + state["messages"] - response = self.llm.invoke(messages) - return {"messages": [response]} - def chat(self, user_input: str): self.messages.append({"role": "user", "content": user_input}) config = {"configurable": {"thread_id": "1"}} @@ -52,10 +34,6 @@ class IntroductionChatbot: return "Thanks for providing all your required business details" in latest_response def extract_details(self): - template = details_extract_prompt(business_state.interactions) - - messages = [SystemMessage(content=template)] - response = self.llm.with_structured_output(DetailsFormatter).invoke(messages) - print('Extracetd details:',response) - return response - + response = extract_business_details(business_state.interactions) + print('Extracted details:', response) + return response \ No newline at end of file diff --git a/context_analysis_agent/utils/__init__.py b/context_analysis_agent/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/context_analysis_agent/utils/__pycache__/__init__.cpython-312.pyc b/context_analysis_agent/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d5c57a1dfa08260db35be8544f5ff1d147b63ee Binary files /dev/null and b/context_analysis_agent/utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/context_analysis_agent/utils/__pycache__/nodes.cpython-312.pyc b/context_analysis_agent/utils/__pycache__/nodes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97a97debab68950e69fd705e2e35a961565fadb4 Binary files /dev/null and b/context_analysis_agent/utils/__pycache__/nodes.cpython-312.pyc differ diff --git a/context_analysis_agent/utils/__pycache__/prompts.cpython-312.pyc b/context_analysis_agent/utils/__pycache__/prompts.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e43d058dc9ef20dadab8f1fef63ed79a27125ef6 Binary files /dev/null and b/context_analysis_agent/utils/__pycache__/prompts.cpython-312.pyc differ diff --git a/context_analysis_agent/utils/__pycache__/state.cpython-312.pyc b/context_analysis_agent/utils/__pycache__/state.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a50c1a40b7a5e3ddff62cd0adafd544b611b700 Binary files /dev/null and b/context_analysis_agent/utils/__pycache__/state.cpython-312.pyc differ diff --git a/context_analysis_agent/utils/__pycache__/utils.cpython-312.pyc b/context_analysis_agent/utils/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..328507d1ea755105317741b09db016b399494014 Binary files /dev/null and b/context_analysis_agent/utils/__pycache__/utils.cpython-312.pyc differ diff --git a/context_analysis_agent/utils/nodes.py b/context_analysis_agent/utils/nodes.py new file mode 100644 index 0000000000000000000000000000000000000000..abc226a82eb2372ebc1e74a06725d76d9f8b1df0 --- /dev/null +++ b/context_analysis_agent/utils/nodes.py @@ -0,0 +1,21 @@ +from langchain_core.messages import SystemMessage +from .prompts import introduction_prompt, details_extract_prompt +from .state import State , DetailsFormatter +from utils.models_loader import llm + +# This node generates chatbot responses using the LLM +def introduction_node(state, llm): + template = introduction_prompt + messages = [SystemMessage(content=template)] + state["messages"] + response = llm.invoke(messages) + return {"messages": [response]} + +# This function extracts structured business details +def extract_business_details(interactions): + template = details_extract_prompt(interactions) + messages = [SystemMessage(content=template)] + response=llm.with_structured_output(DetailsFormatter).invoke(messages) + return response + + + \ No newline at end of file diff --git a/context_analysis_agent/utils/prompts.py b/context_analysis_agent/utils/prompts.py new file mode 100644 index 0000000000000000000000000000000000000000..0ad683c095d9850c96fe51565a23daafe9d22da2 --- /dev/null +++ b/context_analysis_agent/utils/prompts.py @@ -0,0 +1,36 @@ +introduction_prompt = ''' +You are a business assistant who collects only valid and relevant data. +Your job is to gather details from business owners in a friendly and conversational manner to understand their business better. Ask in very easy and short way. + +We need these details: +1. Business Type (e.g., e-commerce, SaaS, consulting), +2. Platform(s) used (e.g., website, app, Instagram), +3. Target Audience (who are their customers or clients), +4. Business Goals (short-term or long-term objectives), +5. Offerings (products or services they provide), +6. Challenges faced (any current business problems or limitations). + +Keep interacting until all valid details are collected. + +VERY IMPORTANT: Once all valid details are received, say: '**Thanks for providing all your required business details.**' + +''' + + +def details_extract_prompt(interactions): + return( f'''Extract the following details of the business from the conversation in the form of dictionary. Don't give any further explanations either in the beginning or ending of the response. + I want the response **direct** in the form of python dictionary. The details you have to extract are:\n + + ----------********--------------- + "business_type": "...", + "platform": "...", + "target_audience": "...", + "business_goals": "...", + "offerings": "...", + "Challenges_faced": "..." + ----------********--------------- + + Now, start doing your work:\n + The conversation is:\n{interactions}\n + ''') + diff --git a/context_analysis_agent/utils/state.py b/context_analysis_agent/utils/state.py new file mode 100644 index 0000000000000000000000000000000000000000..a03b6597ca18d025a8576aea2efb2e9b4e4552b2 --- /dev/null +++ b/context_analysis_agent/utils/state.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel, ConfigDict , Field +from typing import Optional + +class State(BaseModel): + interactions: Optional[list] = [] + model_config = ConfigDict(arbitrary_types_allowed=True) + +# Pydantic model for extracted business info +class DetailsFormatter(BaseModel): + business_type: str = Field(description="The type of the business") + platform: str = Field(description="The platform used for the business") + target_audience: str = Field(description="The target audience of the business") + business_goals: str = Field(description="The business goals of the business") + offerings: str = Field(description="The offerings of the business") + Challenges_faced: str = Field(description="The challenges faced by the business") \ No newline at end of file diff --git a/context_analysis_agent/utils/tools.py b/context_analysis_agent/utils/tools.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/context_analysis_agent/utils/utils.py b/context_analysis_agent/utils/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..e5d7d12ba3ca5b4c65f99aafd82f161fb2826fcb --- /dev/null +++ b/context_analysis_agent/utils/utils.py @@ -0,0 +1,28 @@ +from utils.data_loader import load_dataset +import pandas as pd +from utils.data_loader import load_influencer_data + +def save_to_db(business_details): + # dataset = load_dataset("subashdvorak/tiktok-agentic-story")['train'] + dataset = load_influencer_data() + df = pd.DataFrame(dataset) + + # 2. Flatten all business detail values to a set of lowercase strings + all_values = set() + for v in business_details.values(): + if isinstance(v, str): + all_values.add(v.lower()) + elif isinstance(v, list): + all_values.update(map(str.lower, map(str, v))) + + # 3. Match rows where ANY column contains ANY of the values + def row_matches(row): + return any( + str(cell).lower().find(val) != -1 + for cell in row + for val in all_values + ) + + # 4. Apply row-wise matching + matched_df = df[df.apply(row_matches, axis=1)] + matched_df.to_csv('extracted_data.csv') diff --git a/main.py b/main.py index d165e1173e1427ff627f5fc474ac231d309e3ea2..669b4822f5d9d04fb3276513477abfc81c34ba8c 100644 --- a/main.py +++ b/main.py @@ -1,16 +1,14 @@ from fastapi import FastAPI , UploadFile , File , Form from fastapi.responses import JSONResponse from pydantic import BaseModel -from my_agent.agent import build_graph +from brainstroming_agent.agent import brainstroming_graph import pandas as pd from typing import Optional , List -from my_agent.utils.initial_interaction import IntroductionChatbot -from my_agent.utils.business_interaction import BusinessInteractionChatbot -from my_agent.utils.utils import save_to_db +from context_analysis_agent.agent import IntroductionChatbot +from business_interaction_agent.agent import BusinessInteractionChatbot +from context_analysis_agent.utils.utils import save_to_db import ast - - -from my_agent.utils.utils import encode_image_to_base64 , generate_final_story, generate_image +from brainstroming_agent.utils.utils import encode_image_to_base64 , generate_final_story, generate_image import json @@ -18,19 +16,19 @@ import json # Store brainstorming results per thread_id app = FastAPI() -introduction_chatbot = IntroductionChatbot() -interaction_chatbot2 = BusinessInteractionChatbot() -graph = build_graph() +context_analysis_graph = IntroductionChatbot() +business_interaction_graph = BusinessInteractionChatbot() +brainstrom_graph = brainstroming_graph() stored_data={} class UserMessage(BaseModel): message: str -@app.post("/business-interaction") -def business_introduction_chat(msg: UserMessage): - response = introduction_chatbot.chat(msg.message) - if introduction_chatbot.is_complete(response): - details = introduction_chatbot.extract_details() +@app.post("/context-analysis") +def context_analysis(msg: UserMessage): + response = context_analysis_graph.chat(msg.message) + if context_analysis_graph.is_complete(response): + details = context_analysis_graph.extract_details() details = details.model_dump() print('Business_details:',details) if isinstance(details, str): @@ -43,10 +41,10 @@ def business_introduction_chat(msg: UserMessage): -@app.post("/business-interaction2") -def business_interaction_chat(interaction: str): +@app.post("/business-interaction") +def business_interaction(interaction: str): business_details = {"business_type": "restaurant", "platform": "instagram", "target_audience": "youths", "business_goals": "to go global", "offerings": "nepali foods", "Challenges_faced": "finding new customers, attracting large customers"} - response = interaction_chatbot2.chat(interaction , business_details) + response = business_interaction_graph.chat(interaction , business_details) return {'response': response} @@ -61,7 +59,7 @@ def brainstroming_endpoint( image_base64_list = [encode_image_to_base64(img) for img in images] # Invoke LangGraph - result = graph.invoke({ + result = brainstrom_graph.invoke({ 'topic': query, 'images': image_base64_list, 'latest_preferred_topics':preferred_topics, diff --git a/my_agent/utils/__pycache__/state.cpython-312.pyc b/my_agent/utils/__pycache__/state.cpython-312.pyc deleted file mode 100644 index 41b3d3af2a061442f753061c6dbcd0388a1b95f3..0000000000000000000000000000000000000000 Binary files a/my_agent/utils/__pycache__/state.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/data_loader.cpython-312.pyc b/utils/__pycache__/data_loader.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9836e9e69f834b6ec7856c0722445a5f5b64bcb Binary files /dev/null and b/utils/__pycache__/data_loader.cpython-312.pyc differ diff --git a/utils/__pycache__/models_loader.cpython-312.pyc b/utils/__pycache__/models_loader.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..603313a5515e9889e434eab50cd1ca8359bc1b13 Binary files /dev/null and b/utils/__pycache__/models_loader.cpython-312.pyc differ diff --git a/my_agent/utils/data_loader.py b/utils/data_loader.py similarity index 52% rename from my_agent/utils/data_loader.py rename to utils/data_loader.py index f6326916966d85a06dc34c43412b9380835f668e..3814439a6338e79dc982be9001f4fafb3df4ae9c 100644 --- a/my_agent/utils/data_loader.py +++ b/utils/data_loader.py @@ -1,10 +1,3 @@ -# from datasets import load_dataset - -# def load_influencer_data(): -# dataset = load_dataset("subashdvorak/tiktok-agentic-story",revision="embedded") -# data= dataset['train'].add_faiss_index('embeddings') -# return data - from datasets import load_dataset @@ -14,7 +7,4 @@ dataset = load_dataset("subashdvorak/tiktok-agentic-story", revision="embedded") data = dataset['train'].add_faiss_index('embeddings') def load_influencer_data(): - return data - - - + return data \ No newline at end of file diff --git a/my_agent/utils/models_loader.py b/utils/models_loader.py similarity index 99% rename from my_agent/utils/models_loader.py rename to utils/models_loader.py index e08388e10934e22cf52edc9ab5f14fd956f2679c..39e349390e85fac5644b02dfa4116bd225384f8c 100644 --- a/my_agent/utils/models_loader.py +++ b/utils/models_loader.py @@ -1,4 +1,3 @@ - from langchain_groq import ChatGroq from sentence_transformers import SentenceTransformer from huggingface_hub import InferenceClient @@ -45,8 +44,3 @@ ST = HFEmbeddingAPI( api_url="https://router.huggingface.co/hf-inference/models/mixedbread-ai/mxbai-embed-large-v1/pipeline/feature-extraction", token=os.environ.get('HUGGINGFACEHUB_ACCESS_TOKEN') ) - - - - -