- Minor changes to the SPIN_SPECIALIST

This commit is contained in:
Josako
2025-02-20 11:35:14 +01:00
parent 25213f2004
commit c037d4135e
7 changed files with 54 additions and 27 deletions

View File

@@ -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 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 participating in the conversation, and information on the company he or she is working for. Try to be as precise as
possible. possible.
Take into account information already gathered in the history (between triple backquotes) and add information found in Take into account information already gathered in the historic lead info (between triple backquotes) and add
the latest reply. information found in the latest reply. Also, some identification information may be given by the end user.
history: historic lead info:
```{history}``` ```{historic_lead_info}```
latest reply: latest reply:
{query} {query}
identification:
{identification}
{custom_description} {custom_description}
expected_output: > expected_output: >

View File

@@ -1,11 +1,11 @@
version: "1.0.0" version: "1.0.0"
name: "Define Identification Questions" name: "Define Identification Questions"
task_description: > task_description: >
Gather the identification information gathered by your team mates , take into account the history (in between triple Gather the identification information gathered by your team mates. Ensure no information in the historic lead
backquotes) of the conversation, and the latest reply of the user. 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. Define questions to be asked to complete the personal and company information for the end user in the conversation.
history: historic lead info:
```{history}``` ```{historic_lead_info}```
latest reply: latest reply:
{query} {query}

View File

@@ -2,10 +2,11 @@ version: "1.0.0"
name: "Rag Consolidation" name: "Rag Consolidation"
task_description: > task_description: >
Your teams have collected answers to a user's query (in between triple backquotes), and collected additional follow-up 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 (in between triple %) to reach their goals. Ensure the answers are provided, and select a maximum of
questions to be asked in order not to overwhelm the user. Make a selection of maximum {nr_of_questions} questions to {nr_of_questions} out of the additional questions to be asked in order not to overwhelm the user. The questions are
be returned to the user. You ensure both answers and additional questions are bundled into 1 clear communication back in no specific order, so don't just pick the first ones, but the ones most appropriate in your opinion!
to the user. Use {language} for your consolidated communication. 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} {custom_description}
Anwers: Anwers:

View File

@@ -1,13 +1,12 @@
version: "1.0.0" version: "1.0.0"
name: "SPIN Information Detection" name: "SPIN Information Detection"
task_description: > task_description: >
Detect the SPIN-context, taking into account the history of the discussion (in between triple backquotes) with main focus on Complement the historic SPIN context (in between triple backquotes) with information found in the latest reply of the
the latest reply (which can contain answers on previously asked questions by the user). Spin elements may already be end user.
provided in the history. Add or refine these with the new input provided in the latest reply of the end user.
{custom_description} {custom_description}
Use the following {tenant_language} to define the SPIN-elements. Use the following {tenant_language} to define the SPIN-elements.
History: Historic SPIN:
```{history}``` ```{historic_spin}```
Latest reply: Latest reply:
{query} {query}
expected_output: > expected_output: >
@@ -16,8 +15,8 @@ expected_output: >
- Problem information: a description of the customer's problems uncovering it's challenges and pain points. - 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. - 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. - 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. - Additional info: Information that does not fit in the above SPIN-categories, but that can be commercially
{custom_expected_output} interesting, including if provided: {custom_expected_output}
metadata: metadata:
author: "Josako" author: "Josako"
date_added: "2025-01-08" date_added: "2025-01-08"

View File

@@ -1,14 +1,14 @@
version: "1.0.0" version: "1.0.0"
name: "SPIN Question Identification" name: "SPIN Question Identification"
task_description: > task_description: >
Define, taking into account the history of the discussion (in between triple backquotes) and the latest reply and the Revise the final SPIN provided by your colleague, and ensure no information is lost from the histoic SPIN and the
currently known SPIN-elements, the top questions that need to be asked to understand the full SPIN context 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. of the customer. If you think this user could be a potential customer, please indicate so.
{custom_description} {custom_description}
Use the following {tenant_language} to define the SPIN-elements. If you have a full SPIN context, just skip and don't Use the following {tenant_language} to define the SPIN-elements. If you have a satisfying SPIN context, just skip and
ask for more information or confirmation. don't ask for more information or confirmation.
History: Historic SPIN:
```{history}``` ```{historic_spin}```
Latest reply: Latest reply:
{query} {query}
expected_output: > expected_output: >

View File

@@ -126,7 +126,9 @@ class SpecialistExecutor(CrewAIBaseSpecialistExecutor):
"query": arguments.query, "query": arguments.query,
"context": formatted_context, "context": formatted_context,
"citations": citations, "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', ''), "name": self.specialist.configuration.get('name', ''),
"company": self.specialist.configuration.get('company', ''), "company": self.specialist.configuration.get('company', ''),
"products": self.specialist.configuration.get('products', ''), "products": self.specialist.configuration.get('products', ''),
@@ -134,6 +136,7 @@ class SpecialistExecutor(CrewAIBaseSpecialistExecutor):
"engagement_options": self.specialist.configuration.get('engagement_options', ''), "engagement_options": self.specialist.configuration.get('engagement_options', ''),
"tenant_language": self.specialist.configuration.get('tenant_language', ''), "tenant_language": self.specialist.configuration.get('tenant_language', ''),
"nr_of_questions": self.specialist.configuration.get('nr_of_questions', ''), "nr_of_questions": self.specialist.configuration.get('nr_of_questions', ''),
"identification": arguments.identification,
} }
# crew_results = self.rag_crew.kickoff(inputs=flow_inputs) # crew_results = self.rag_crew.kickoff(inputs=flow_inputs)
# current_app.logger.debug(f"Test Crew Output received: {crew_results}") # 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") context: Optional[str] = Field(None, alias="context")
citations: Optional[List[int]] = Field(None, alias="citations") citations: Optional[List[int]] = Field(None, alias="citations")
history: Optional[str] = Field(None, alias="history") 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") name: Optional[str] = Field(None, alias="name")
company: Optional[str] = Field(None, alias="company") company: Optional[str] = Field(None, alias="company")
products: Optional[str] = Field(None, alias="products") products: Optional[str] = Field(None, alias="products")
@@ -174,6 +179,7 @@ class SPINSpecialistInput(BaseModel):
engagement_options: Optional[str] = Field(None, alias="engagement_options") engagement_options: Optional[str] = Field(None, alias="engagement_options")
tenant_language: Optional[str] = Field(None, alias="tenant_language") tenant_language: Optional[str] = Field(None, alias="tenant_language")
nr_of_questions: Optional[int] = Field(None, alias="nr_of_questions") nr_of_questions: Optional[int] = Field(None, alias="nr_of_questions")
identification: Optional[str] = Field(None, alias="identification")
class SPINSpecialistResult(SpecialistResult): class SPINSpecialistResult(SpecialistResult):
@@ -266,6 +272,7 @@ class SPINFlow(EveAICrewAIFlow[SPINFlowState]):
additional_questions = self.state.lead_info.questions + "\n" additional_questions = self.state.lead_info.questions + "\n"
if self.state.spin: if self.state.spin:
additional_questions = additional_questions + self.state.spin.questions additional_questions = additional_questions + self.state.spin.questions
current_app.logger.debug(f"Additional Questions: {additional_questions}")
inputs["additional_questions"] = additional_questions inputs["additional_questions"] = additional_questions
try: try:
crew_output = self.rag_consolidation_crew.kickoff(inputs=inputs) crew_output = self.rag_consolidation_crew.kickoff(inputs=inputs)

View File

@@ -71,6 +71,14 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor):
for interaction in self._cached_session.interactions 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): def _add_task_agent(self, task_name: str, agent_name: str):
self._task_agents[task_name.lower()] = agent_name self._task_agents[task_name.lower()] = agent_name
@@ -155,7 +163,10 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor):
pass pass
def __getattr__(self, name: str) -> Any: 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: try:
if name.endswith('_agent'): if name.endswith('_agent'):
return self._agents[name] return self._agents[name]
@@ -166,6 +177,13 @@ class CrewAIBaseSpecialistExecutor(BaseSpecialistExecutor):
if name.endswith('_tool'): if name.endswith('_tool'):
return self._tools[name] 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 # Not a known component request
raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{name}'") raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{name}'")
except KeyError: except KeyError: