diff --git a/config/tasks/IDENTIFICATION_DETECTION_TASK/1.0.0.yaml b/config/tasks/IDENTIFICATION_DETECTION_TASK/1.0.0.yaml index 2d17199..b80a846 100644 --- a/config/tasks/IDENTIFICATION_DETECTION_TASK/1.0.0.yaml +++ b/config/tasks/IDENTIFICATION_DETECTION_TASK/1.0.0.yaml @@ -4,13 +4,15 @@ task_description: > You are asked to gather lead information in a conversation with a new prospect. This is information about the person participating in the conversation, and information on the company he or she is working for. Try to be as precise as possible. - Take into account information already gathered in the history (between triple backquotes) and add information found in - the latest reply. + Take into account information already gathered in the historic lead info (between triple backquotes) and add + information found in the latest reply. Also, some identification information may be given by the end user. - history: - ```{history}``` + historic lead info: + ```{historic_lead_info}``` latest reply: {query} + identification: + {identification} {custom_description} expected_output: > diff --git a/config/tasks/IDENTIFICATION_QUESTIONS_TASK/1.0.0.yaml b/config/tasks/IDENTIFICATION_QUESTIONS_TASK/1.0.0.yaml index 14a39f1..ad35ad0 100644 --- a/config/tasks/IDENTIFICATION_QUESTIONS_TASK/1.0.0.yaml +++ b/config/tasks/IDENTIFICATION_QUESTIONS_TASK/1.0.0.yaml @@ -1,11 +1,11 @@ version: "1.0.0" name: "Define Identification Questions" task_description: > - Gather the identification information gathered by your team mates , take into account the history (in between triple - backquotes) of the conversation, and the latest reply of the user. + Gather the identification information gathered by your team mates. Ensure no information in the historic lead + information (in between triple backquotes) and the latest reply of the user is lost. Define questions to be asked to complete the personal and company information for the end user in the conversation. - history: - ```{history}``` + historic lead info: + ```{historic_lead_info}``` latest reply: {query} diff --git a/config/tasks/RAG_CONSOLIDATION_TASK/1.0.0.yaml b/config/tasks/RAG_CONSOLIDATION_TASK/1.0.0.yaml index 5591870..f67aab1 100644 --- a/config/tasks/RAG_CONSOLIDATION_TASK/1.0.0.yaml +++ b/config/tasks/RAG_CONSOLIDATION_TASK/1.0.0.yaml @@ -2,10 +2,11 @@ version: "1.0.0" name: "Rag Consolidation" task_description: > Your teams have collected answers to a user's query (in between triple backquotes), and collected additional follow-up - questions (in between triple %) to reach their goals. Ensure the answers are provided, and select the additional - questions to be asked in order not to overwhelm the user. Make a selection of maximum {nr_of_questions} questions to - be returned to the user. You ensure both answers and additional questions are bundled into 1 clear communication back - to the user. Use {language} for your consolidated communication. + questions (in between triple %) to reach their goals. Ensure the answers are provided, and select a maximum of + {nr_of_questions} out of the additional questions to be asked in order not to overwhelm the user. The questions are + in no specific order, so don't just pick the first ones, but the ones most appropriate in your opinion! + Questions are to be asked when your team proposes questions. You ensure both answers and additional questions are + bundled into 1 clear communication back to the user. Use {language} for your consolidated communication. {custom_description} Anwers: diff --git a/config/tasks/SPIN_DETECT_TASK/1.0.0.yaml b/config/tasks/SPIN_DETECT_TASK/1.0.0.yaml index 522f263..64e13c9 100644 --- a/config/tasks/SPIN_DETECT_TASK/1.0.0.yaml +++ b/config/tasks/SPIN_DETECT_TASK/1.0.0.yaml @@ -1,13 +1,12 @@ version: "1.0.0" name: "SPIN Information Detection" task_description: > - Detect the SPIN-context, taking into account the history of the discussion (in between triple backquotes) with main focus on - the latest reply (which can contain answers on previously asked questions by the user). Spin elements may already be - provided in the history. Add or refine these with the new input provided in the latest reply of the end user. + Complement the historic SPIN context (in between triple backquotes) with information found in the latest reply of the + end user. {custom_description} Use the following {tenant_language} to define the SPIN-elements. - History: - ```{history}``` + Historic SPIN: + ```{historic_spin}``` Latest reply: {query} expected_output: > @@ -16,8 +15,8 @@ expected_output: > - Problem information: a description of the customer's problems uncovering it's challenges and pain points. - Implication information: implications of situation / identified problems, i.e. of the consequences of those problems. - Need-payoff information: Customer's needs, helping customers realize value of solutions. - - Additional info: Information that does not fit in the above SPIN-categories, but that can be commercially interesting. - {custom_expected_output} + - Additional info: Information that does not fit in the above SPIN-categories, but that can be commercially + interesting, including if provided: {custom_expected_output} metadata: author: "Josako" date_added: "2025-01-08" diff --git a/config/tasks/SPIN_QUESTIONS_TASK/1.0.0.yaml b/config/tasks/SPIN_QUESTIONS_TASK/1.0.0.yaml index df2d7cf..b35ea1b 100644 --- a/config/tasks/SPIN_QUESTIONS_TASK/1.0.0.yaml +++ b/config/tasks/SPIN_QUESTIONS_TASK/1.0.0.yaml @@ -1,14 +1,14 @@ version: "1.0.0" name: "SPIN Question Identification" task_description: > - Define, taking into account the history of the discussion (in between triple backquotes) and the latest reply and the - currently known SPIN-elements, the top questions that need to be asked to understand the full SPIN context + Revise the final SPIN provided by your colleague, and ensure no information is lost from the histoic SPIN and the + latest reply from the user. Define the top questions that need to be asked to understand the full SPIN context of the customer. If you think this user could be a potential customer, please indicate so. {custom_description} - Use the following {tenant_language} to define the SPIN-elements. If you have a full SPIN context, just skip and don't - ask for more information or confirmation. - History: - ```{history}``` + Use the following {tenant_language} to define the SPIN-elements. If you have a satisfying SPIN context, just skip and + don't ask for more information or confirmation. + Historic SPIN: + ```{historic_spin}``` Latest reply: {query} expected_output: > diff --git a/eveai_chat_workers/specialists/SPIN_SPECIALIST/1_0.py b/eveai_chat_workers/specialists/SPIN_SPECIALIST/1_0.py index b37aa26..fd8ac5b 100644 --- a/eveai_chat_workers/specialists/SPIN_SPECIALIST/1_0.py +++ b/eveai_chat_workers/specialists/SPIN_SPECIALIST/1_0.py @@ -126,7 +126,9 @@ class SpecialistExecutor(CrewAIBaseSpecialistExecutor): "query": arguments.query, "context": formatted_context, "citations": citations, - "history": self._formatted_history, + "history": self.formatted_history, + "historic_spin": json.dumps(self.latest_spin, indent=2), + "historic_lead_info": json.dumps(self.latest_lead_info, indent=2), "name": self.specialist.configuration.get('name', ''), "company": self.specialist.configuration.get('company', ''), "products": self.specialist.configuration.get('products', ''), @@ -134,6 +136,7 @@ class SpecialistExecutor(CrewAIBaseSpecialistExecutor): "engagement_options": self.specialist.configuration.get('engagement_options', ''), "tenant_language": self.specialist.configuration.get('tenant_language', ''), "nr_of_questions": self.specialist.configuration.get('nr_of_questions', ''), + "identification": arguments.identification, } # crew_results = self.rag_crew.kickoff(inputs=flow_inputs) # current_app.logger.debug(f"Test Crew Output received: {crew_results}") @@ -167,6 +170,8 @@ class SPINSpecialistInput(BaseModel): context: Optional[str] = Field(None, alias="context") citations: Optional[List[int]] = Field(None, alias="citations") history: Optional[str] = Field(None, alias="history") + historic_spin: Optional[str] = Field(None, alias="historic_spin") + historic_lead_info: Optional[str] = Field(None, alias="historic_lead_info") name: Optional[str] = Field(None, alias="name") company: Optional[str] = Field(None, alias="company") products: Optional[str] = Field(None, alias="products") @@ -174,6 +179,7 @@ class SPINSpecialistInput(BaseModel): engagement_options: Optional[str] = Field(None, alias="engagement_options") tenant_language: Optional[str] = Field(None, alias="tenant_language") nr_of_questions: Optional[int] = Field(None, alias="nr_of_questions") + identification: Optional[str] = Field(None, alias="identification") class SPINSpecialistResult(SpecialistResult): @@ -266,6 +272,7 @@ class SPINFlow(EveAICrewAIFlow[SPINFlowState]): additional_questions = self.state.lead_info.questions + "\n" if self.state.spin: additional_questions = additional_questions + self.state.spin.questions + current_app.logger.debug(f"Additional Questions: {additional_questions}") inputs["additional_questions"] = additional_questions try: crew_output = self.rag_consolidation_crew.kickoff(inputs=inputs) diff --git a/eveai_chat_workers/specialists/crewai_base_specialist.py b/eveai_chat_workers/specialists/crewai_base_specialist.py index e9b13d0..5c6adfd 100644 --- a/eveai_chat_workers/specialists/crewai_base_specialist.py +++ b/eveai_chat_workers/specialists/crewai_base_specialist.py @@ -71,6 +71,14 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor): for interaction in self._cached_session.interactions ]) + @property + def formatted_history(self) -> str: + formatted_history = "\n\n".join([ + f"HUMAN:\n{interaction.specialist_results.get('query')}\n\n" + f"AI:\n{interaction.specialist_results.get('rag_output').get('answer', '')}" + for interaction in self._cached_session.interactions + ]) + def _add_task_agent(self, task_name: str, agent_name: str): self._task_agents[task_name.lower()] = agent_name @@ -155,7 +163,10 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor): pass def __getattr__(self, name: str) -> Any: - """Enable dynamic access to agents as attributes""" + """ + - Enable dynamic access to agents, tasks or tools as attributes + - Enable dynamic access to latest information in interactions in the cached session + """ try: if name.endswith('_agent'): return self._agents[name] @@ -166,6 +177,13 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor): if name.endswith('_tool'): return self._tools[name] + if name.startswith('latest_'): + element = name[len('latest_'):] + if self._cached_session.interactions: + return self._cached_session.interactions[-1].get(element, '') + else: + return {} + # Not a known component request raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{name}'") except KeyError: