- Move global config files to globals iso global folder, as the name global conflicts with python language

- Creation of Traicie Vancancy Definition specialist
- Allow to invoke non-interaction specialists from withing Evie's mgmt interface (eveai_app)
- Improvements to crewai specialized classes
- Introduction to json editor for showing specialists arguments and results in a better way
- Introduction of more complex pagination (adding extra arguments) by adding a global 'get_pagination_html'
- Allow follow-up of ChatSession / Specialist execution
- Improvement in logging of Specialists (but needs to be finished)
This commit is contained in:
Josako
2025-05-26 11:26:03 +02:00
parent d789e431ca
commit 1fdbd2ff45
94 changed files with 1657 additions and 443 deletions

View File

@@ -0,0 +1,29 @@
version: "1.0.0"
name: "Traicie HR BP "
role: >
You are an HR BP (Human Resources Business Partner)
goal: >
As an HR Business Partner, your primary goal is to align people strategies with business objectives. You aim to
ensure that the organisation has the right talent, capabilities, and culture in place to drive performance,
manage change effectively, and support sustainable growth. This involves acting as a trusted advisor to leadership
while advocating for employees and fostering a healthy, high-performing workplace.
{custom_goal}
backstory: >
You didn't start your career as a strategist. You began in traditional HR roles — perhaps as an HR officer or
generalist — mastering recruitment, employee relations, and policy implementation. Over time, you developed a deeper
understanding of how people decisions impact business outcomes.
Through experience, exposure to leadership, and a strong interest in organisational dynamics, you transitioned into a
role that bridges the gap between HR and the business. Youve earned a seat at the table not just by knowing HR
processes, but by understanding the business inside-out, speaking the language of executives, and backing their advice
with data and insight.
You often working side-by-side with senior managers to tackle challenges like workforce planning, leadership
development, organisational change, and employee engagement. Your credibility comes not just from HR knowledge,
but from your ability to co-create solutions that solve real business problems.
{custom_backstory}
full_model_name: "mistral.mistral-medium-latest"
temperature: 0.3
metadata:
author: "Josako"
date_added: "2025-05-21"
description: "HR BP Agent."
changes: "Initial version"

View File

@@ -0,0 +1,19 @@
version: "1.0.0"
name: "Specialist Configuration"
configuration:
specialist_type:
name: "Specialist Type"
type: "str"
description: "The Specialist Type this configuration is made for"
required: True
specialist_version:
name: "Specialist Version"
type: "str"
description: "The Specialist Type version this configuration is made for"
required: True
metadata:
author: "Josako"
date_added: "2025-05-21"
description: "Asset that defines a template in markdown a specialist can process"
changes: "Initial version"

View File

@@ -47,6 +47,7 @@ class TuningLogRecord(logging.LogRecord):
self._tuning_specialist_id = None
self._tuning_retriever_id = None
self._tuning_processor_id = None
self._session_id = None
self.component = os.environ.get('COMPONENT_NAME', 'eveai_app')
def getMessage(self):
@@ -87,16 +88,18 @@ class TuningLogRecord(logging.LogRecord):
'tuning_specialist_id': self._tuning_specialist_id,
'tuning_retriever_id': self._tuning_retriever_id,
'tuning_processor_id': self._tuning_processor_id,
'session_id': self._session_id,
}
def set_tuning_data(self, tenant_id=None, catalog_id=None, specialist_id=None,
retriever_id=None, processor_id=None):
retriever_id=None, processor_id=None, session_id=None,):
"""Set tuning-specific data"""
object.__setattr__(self, '_tuning_tenant_id', tenant_id)
object.__setattr__(self, '_tuning_catalog_id', catalog_id)
object.__setattr__(self, '_tuning_specialist_id', specialist_id)
object.__setattr__(self, '_tuning_retriever_id', retriever_id)
object.__setattr__(self, '_tuning_processor_id', processor_id)
object.__setattr__(self, '_session_id', session_id)
class TuningFormatter(logging.Formatter):
@@ -120,6 +123,12 @@ class TuningFormatter(logging.Formatter):
identifiers.append(f"Catalog: {record.catalog_id}")
if hasattr(record, 'processor_id') and record.processor_id:
identifiers.append(f"Processor: {record.processor_id}")
if hasattr(record, 'specialist_id') and record.specialist_id:
identifiers.append(f"Specialist: {record.specialist_id}")
if hasattr(record, 'retriever_id') and record.retriever_id:
identifiers.append(f"Retriever: {record.retriever_id}")
if hasattr(record, 'session_id') and record.session_id:
identifiers.append(f"Session: {record.session_id}")
formatted_msg = (
f"{formatted_msg}\n"
@@ -149,22 +158,93 @@ class GraylogFormatter(logging.Formatter):
'specialist_id': record.specialist_id,
'retriever_id': record.retriever_id,
'processor_id': record.processor_id,
'session_id': record.session_id,
}
return super().format(record)
class TuningLogger:
"""Helper class to manage tuning logs with consistent structure"""
def __init__(self, logger_name, tenant_id=None, catalog_id=None, specialist_id=None, retriever_id=None, processor_id=None):
def __init__(self, logger_name, tenant_id=None, catalog_id=None, specialist_id=None, retriever_id=None,
processor_id=None, session_id=None, log_file=None):
"""
Initialize a tuning logger
Args:
logger_name: Base name for the logger
tenant_id: Optional tenant ID for context
catalog_id: Optional catalog ID for context
specialist_id: Optional specialist ID for context
retriever_id: Optional retriever ID for context
processor_id: Optional processor ID for context
session_id: Optional session ID for context and log file naming
log_file: Optional custom log file name to use
"""
self.logger = logging.getLogger(logger_name)
self.tenant_id = tenant_id
self.catalog_id = catalog_id
self.specialist_id = specialist_id
self.retriever_id = retriever_id
self.processor_id = processor_id
self.session_id = session_id
self.log_file = log_file
# Determine whether to use a session-specific logger
if session_id:
# Create a unique logger name for this session
session_logger_name = f"{logger_name}_{session_id}"
self.logger = logging.getLogger(session_logger_name)
def log_tuning(self, tuning_type: str, message: str, data=None, level=logging.DEBUG):
# If this logger doesn't have handlers yet, configure it
if not self.logger.handlers:
# Determine log file path
if not log_file and session_id:
log_file = f"logs/tuning_{session_id}.log"
elif not log_file:
log_file = "logs/tuning.log"
# Configure the logger
self._configure_session_logger(log_file)
else:
# Use the standard tuning logger
self.logger = logging.getLogger(logger_name)
def _configure_session_logger(self, log_file):
"""Configure a new session-specific logger with appropriate handlers"""
# Create and configure a file handler
file_handler = logging.handlers.RotatingFileHandler(
filename=log_file,
maxBytes=1024 * 1024 * 3, # 3MB
backupCount=3
)
file_handler.setFormatter(TuningFormatter())
file_handler.setLevel(logging.DEBUG)
# Add the file handler to the logger
self.logger.addHandler(file_handler)
# Add Graylog handler in production
env = os.environ.get('FLASK_ENV', 'development')
if env == 'production':
try:
graylog_handler = GELFUDPHandler(
host=GRAYLOG_HOST,
port=GRAYLOG_PORT,
debugging_fields=True
)
graylog_handler.setFormatter(GraylogFormatter())
self.logger.addHandler(graylog_handler)
except Exception as e:
# Fall back to just file logging if Graylog setup fails
fallback_logger = logging.getLogger('eveai_app')
fallback_logger.warning(f"Failed to set up Graylog handler: {str(e)}")
# Set logger level and disable propagation
self.logger.setLevel(logging.DEBUG)
self.logger.propagate = False
def log_tuning(self, tuning_type: str, message: str, data=None, level=logging.DEBUG):
"""Log a tuning event with structured data"""
try:
# Create a standard LogRecord for tuning
@@ -186,6 +266,7 @@ class TuningLogger:
record.specialist_id = self.specialist_id
record.retriever_id = self.retriever_id
record.processor_id = self.processor_id
record.session_id = self.session_id
if data:
record.tuning_data = data

View File

@@ -1,6 +1,11 @@
version: "1.0.0"
name: "Management Service"
configuration: {}
configuration:
specialist_denominator:
name: "Specialist Denominator"
type: "string"
description: "Name defining the denominator for the specialist. Needs to be unique."
required: False
permissions: {}
metadata:
author: "Josako"

View File

@@ -1,163 +0,0 @@
version: "1.0.0"
name: "Traicie Vacature Specialist"
framework: "crewai"
configuration:
ko_criteria:
name: "Knock-out criteria"
type: "text"
description: "The knock-out criteria (1 per line)"
required: true
hard_skills:
name: "Hard Skills"
type: "text"
description: "The hard skills to be checked with the applicant (1 per line)"
required: false
soft_skills:
name: "Soft Skills"
type: "text"
description: "The soft skills required for the job (1 per line)"
required: false
tone_of_voice:
name: "Tone of Voice"
type: "enum"
description: "Tone of voice to be used in communicating with the applicant"
required: false
default: "formal"
allowed_values: [ "formal", "informal", "dynamic" ]
vacancy_text:
name: "Vacancy Text"
type: "text"
description: "The vacancy for this specialist"
arguments:
language:
name: "Language"
type: "str"
description: "Language code to be used for receiving questions and giving answers"
required: true
results:
rag_output:
answer:
name: "answer"
type: "str"
description: "Answer to the query"
required: true
citations:
name: "citations"
type: "List[str]"
description: "List of citations"
required: false
insufficient_info:
name: "insufficient_info"
type: "bool"
description: "Whether or not the query is insufficient info"
required: true
spin:
situation:
name: "situation"
type: "str"
description: "A description of the customer's current situation / context"
required: false
problem:
name: "problem"
type: "str"
description: "The current problems the customer is facing, for which he/she seeks a solution"
required: false
implication:
name: "implication"
type: "str"
description: "A list of implications"
required: false
needs:
name: "needs"
type: "str"
description: "A list of needs"
required: false
additional_info:
name: "additional_info"
type: "str"
description: "Additional information that may be commercially interesting"
required: false
lead_info:
lead_personal_info:
name:
name: "name"
type: "str"
description: "name of the lead"
required: "true"
job_title:
name: "job_title"
type: "str"
description: "job title"
required: false
email:
name: "email"
type: "str"
description: "lead email"
required: "false"
phone:
name: "phone"
type: "str"
description: "lead phone"
required: false
additional_info:
name: "additional_info"
type: "str"
description: "additional info on the lead"
required: false
lead_company_info:
company_name:
name: "company_name"
type: "str"
description: "Name of the lead company"
required: false
industry:
name: "industry"
type: "str"
description: "The industry of the company"
required: false
company_size:
name: "company_size"
type: "int"
description: "The size of the company"
required: false
company_website:
name: "company_website"
type: "str"
description: "The main website for the company"
required: false
additional_info:
name: "additional_info"
type: "str"
description: "Additional information that may be commercially interesting"
required: false
agents:
- type: "RAG_AGENT"
version: "1.0"
- type: "RAG_COMMUNICATION_AGENT"
version: "1.0"
- type: "SPIN_DETECTION_AGENT"
version: "1.0"
- type: "SPIN_SALES_SPECIALIST_AGENT"
version: "1.0"
- type: "IDENTIFICATION_AGENT"
version: "1.0"
- type: "RAG_COMMUNICATION_AGENT"
version: "1.0"
tasks:
- type: "RAG_TASK"
version: "1.0"
- type: "SPIN_DETECT_TASK"
version: "1.0"
- type: "SPIN_QUESTIONS_TASK"
version: "1.0"
- type: "IDENTIFICATION_DETECTION_TASK"
version: "1.0"
- type: "IDENTIFICATION_QUESTIONS_TASK"
version: "1.0"
- type: "RAG_CONSOLIDATION_TASK"
version: "1.0"
metadata:
author: "Josako"
date_added: "2025-01-08"
changes: "Initial version"
description: "A Specialist that performs both Q&A as SPIN (Sales Process) activities"

View File

@@ -1,6 +1,7 @@
version: "1.0.0"
name: "RAG Specialist"
framework: "crewai"
chat: true
configuration:
name:
name: "name"

View File

@@ -1,6 +1,7 @@
version: "1.0.0"
name: "Spin Sales Specialist"
framework: "crewai"
chat: true
configuration:
name:
name: "name"

View File

Before

Width:  |  Height:  |  Size: 387 KiB

After

Width:  |  Height:  |  Size: 387 KiB

View File

@@ -1,6 +1,7 @@
version: 1.0.0
name: "Standard RAG Specialist"
framework: "langchain"
chat: true
configuration:
specialist_context:
name: "Specialist Context"

View File

@@ -0,0 +1,36 @@
version: "1.0.0"
name: "Traicie Vacancy Definition Specialist"
framework: "crewai"
partner: "traicie"
chat: false
configuration: {}
arguments:
vacancy_text:
name: "vacancy_text"
type: "text"
description: "The Vacancy Text"
required: true
results:
competencies:
name: "competencies"
type: "List[str, str]"
description: "List of vacancy competencies and their descriptions"
required: false
criteria:
name: "criteria"
type: "List[str, str]"
description: "List of vacancy knock out criteria and their descriptions"
required: false
agents:
- type: "TRAICIE_HR_BP_AGENT"
version: "1.0"
tasks:
- type: "TRAICIE_GET_COMPETENCIES_TASK"
version: "1.0"
- type: "TRAICIE_GET_KO_CRITERIA_TASK"
version: "1.0"
metadata:
author: "Josako"
date_added: "2025-05-21"
changes: "Initial version"
description: "Assistant to create a new Vacancy based on Vacancy Text"

View File

@@ -0,0 +1,28 @@
version: "1.0.0"
name: "Get Competencies"
task_description: >
You are provided with a vacancy text, in beween triple backquotes.
Identify and list all explicitly stated competencies, skills, knowledge, qualifications, and requirements mentioned in
the vacancy text. This includes:
• Technical skills
• Education or training
• Work experience
• Language proficiency
• Certifications or driving licences
• Personal characteristics
Restrict yourself strictly to what is literally stated or clearly described in the job posting.
Respect the language of the vacancy text, and return answers / output in the same language.
{custom_description}
Vacancy Text:
```{vacancy_text}```
expected_output: >
A list of title and description of the competencies for the given vacancy text.
{custom_expected_output}
metadata:
author: "Josako"
date_added: "2025-01-25"
description: "A Task to collect all behavioural competencies from a vacancy text"
changes: "Initial version"

View File

@@ -0,0 +1,37 @@
version: "1.0.0"
name: "Get KO Criteria"
task_description: >
You are provided with a vacancy text, in beween triple backquotes.
Use logical reasoning based on the realities of the job, taking into account:
• The job title
• The content of the job description
• Typical characteristics of similar roles
Identify the minimum requirements that are absolutely essential to perform the job properly even if they are not
explicitly stated in the text.
Assess the job within its specific context and ask yourself questions such as:
• Does the job require physical stamina?
• Is weekend or shift work involved?
• Is contact with certain materials (e.g. meat, chemicals) unavoidable?
• Is independent working essential?
• Is knowledge of a specific language or system critical for customer interaction or safety?
• Are there any specific characteristics, contexts, or requirements so obvious that they are often left unstated, yet essential to perform the job?
Create a prioritised list of the 5 most critical knock-out criteria, ranked by importance.
Treat this as a logical and professional reasoning exercise.
Respect the language of the vacancy text, and return answers / output in the same language.
{custom_description}
Vacancy Text:
```{vacancy_text}```
expected_output: >
A list of title and description of the (knock-out) criteria for the given vacancy text.
{custom_expected_output}
metadata:
author: "Josako"
date_added: "2025-01-25"
description: "A Task to collect all KO criteria from a vacancy text"
changes: "Initial version"

View File

@@ -28,4 +28,9 @@ AGENT_TYPES = {
"name": "SPIN Sales Specialist",
"description": "An Agent that asks for Follow-up questions for SPIN-process",
},
"TRAICIE_HR_BP_AGENT": {
"name": "Traicie HR BP Agent",
"description": "An HR Business Partner Agent",
"partner": "traicie"
}
}

View File

@@ -4,4 +4,8 @@ AGENT_TYPES = {
"name": "Document Template",
"description": "Asset that defines a template in markdown a specialist can process",
},
"SPECIALIST_CONFIGURATION": {
"name": "Specialist Configuration",
"description": "Asset that defines a specialist configuration",
},
}

View File

@@ -12,9 +12,9 @@ SPECIALIST_TYPES = {
"name": "Spin Sales Specialist",
"description": "A specialist that allows to answer user queries, try to get SPIN-information and Identification",
},
"TRAICIE_VACATURE_SPECIALIST": {
"name": "Traicie Vacature Specialist",
"description": "Specialist configureerbaar voor een specifieke vacature",
"partner": "Traicie"
"TRAICIE_VACANCY_DEFINITION_SPECIALIST": {
"name": "Traicie Vacancy Definition Specialist",
"description": "Assistant to create a new Vacancy based on Vacancy Text",
"partner": "traicie"
}
}

View File

@@ -31,5 +31,15 @@ TASK_TYPES = {
"RAG_CONSOLIDATION_TASK": {
"name": "RAG Consolidation",
"description": "A Task to consolidate questions and answers",
},
"TRAICIE_GET_COMPETENCIES_TASK": {
"name": "Traicie Get Competencies",
"description": "A Task to get Competencies from a Vacancy Text",
"partner": "traicie"
},
"TRAICIE_GET_KO_CRITERIA_TASK": {
"name": "Traicie Get KO Criteria",
"description": "A Task to get KO Criteria from a Vacancy Text",
"partner": "traicie"
}
}