unique_orchestrator 1.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of unique_orchestrator might be problematic. Click here for more details.

@@ -0,0 +1,401 @@
1
+ from enum import StrEnum
2
+ from pathlib import Path
3
+ from typing import Annotated, Any, Generic, Literal, TypeVar
4
+
5
+ from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator
6
+ from unique_deep_research.config import DeepResearchToolConfig
7
+ from unique_deep_research.service import DeepResearchTool
8
+ from unique_follow_up_questions.config import FollowUpQuestionsConfig
9
+ from unique_internal_search.config import InternalSearchConfig
10
+ from unique_internal_search.service import InternalSearchTool
11
+ from unique_stock_ticker.config import StockTickerConfig
12
+ from unique_swot import SwotAnalysisTool, SwotAnalysisToolConfig
13
+ from unique_toolkit._common.validators import (
14
+ LMI,
15
+ ClipInt,
16
+ get_LMI_default_field,
17
+ )
18
+ from unique_toolkit.agentic.evaluation.hallucination.constants import (
19
+ HallucinationConfig,
20
+ )
21
+ from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricName
22
+ from unique_toolkit.agentic.history_manager.history_manager import (
23
+ UploadedContentConfig,
24
+ )
25
+ from unique_toolkit.agentic.loop_runner import (
26
+ QWEN_FORCED_TOOL_CALL_INSTRUCTION,
27
+ QWEN_LAST_ITERATION_INSTRUCTION,
28
+ PlanningConfig,
29
+ )
30
+ from unique_toolkit.agentic.responses_api import (
31
+ DisplayCodeInterpreterFilesPostProcessorConfig,
32
+ ShowExecutedCodePostprocessorConfig,
33
+ )
34
+ from unique_toolkit.agentic.tools.a2a import (
35
+ REFERENCING_INSTRUCTIONS_FOR_SYSTEM_PROMPT,
36
+ REFERENCING_INSTRUCTIONS_FOR_USER_PROMPT,
37
+ )
38
+ from unique_toolkit.agentic.tools.a2a.evaluation import SubAgentEvaluationServiceConfig
39
+ from unique_toolkit.agentic.tools.config import get_configuration_dict
40
+ from unique_toolkit.agentic.tools.openai_builtin.manager import (
41
+ OpenAICodeInterpreterConfig,
42
+ )
43
+ from unique_toolkit.agentic.tools.tool import ToolBuildConfig
44
+ from unique_toolkit.agentic.tools.tool_progress_reporter import (
45
+ ToolProgressReporterConfig,
46
+ )
47
+ from unique_toolkit.language_model.default_language_model import DEFAULT_GPT_4o
48
+ from unique_web_search.config import WebSearchConfig
49
+ from unique_web_search.service import WebSearchTool
50
+
51
+ DeactivatedNone = Annotated[
52
+ None,
53
+ Field(title="Deactivated", description="None"),
54
+ ]
55
+
56
+
57
+ class SpaceType(StrEnum):
58
+ UNIQUE_CUSTOM = "unique_custom"
59
+ UNIQUE_AI = "unique_ai"
60
+ UNIQUE_TRANSLATION = "unique_translation"
61
+ UNIQUE_MAGIC_TABLE = ""
62
+
63
+
64
+ T = TypeVar("T", bound=SpaceType)
65
+
66
+
67
+ class SpaceConfigBase(BaseModel, Generic[T]):
68
+ """Base class for space configuration."""
69
+
70
+ model_config = get_configuration_dict(frozen=True)
71
+ type: T = Field(description="The type of the space.")
72
+
73
+ project_name: str = Field(
74
+ default="Unique AI",
75
+ description="The project name as optained from spaces 2.0",
76
+ )
77
+
78
+ language_model: LMI = get_LMI_default_field(DEFAULT_GPT_4o)
79
+
80
+ custom_instructions: str = Field(
81
+ default="",
82
+ description="A custom instruction provided by the system admin.",
83
+ )
84
+
85
+ tools: list[ToolBuildConfig] = Field(
86
+ default=[
87
+ ToolBuildConfig(
88
+ name=InternalSearchTool.name,
89
+ configuration=InternalSearchConfig(
90
+ exclude_uploaded_files=True,
91
+ ),
92
+ ),
93
+ ToolBuildConfig(
94
+ name=WebSearchTool.name,
95
+ configuration=WebSearchConfig(),
96
+ ),
97
+ ToolBuildConfig(
98
+ name=DeepResearchTool.name,
99
+ configuration=DeepResearchToolConfig(),
100
+ ),
101
+ ToolBuildConfig(
102
+ name=SwotAnalysisTool.name,
103
+ configuration=SwotAnalysisToolConfig(),
104
+ ),
105
+ ],
106
+ )
107
+
108
+ @field_validator("tools", mode="after")
109
+ @classmethod
110
+ def set_input_context_size(
111
+ cls, tools: list[ToolBuildConfig], info: ValidationInfo
112
+ ) -> list[ToolBuildConfig]:
113
+ for tool in tools:
114
+ if tool.name == InternalSearchTool.name:
115
+ tool.configuration.language_model_max_input_tokens = ( # type: ignore
116
+ info.data["language_model"].token_limits.token_limit_input
117
+ )
118
+ elif tool.name == WebSearchTool.name:
119
+ tool.configuration.language_model_max_input_tokens = ( # type: ignore
120
+ info.data["language_model"].token_limits.token_limit_input
121
+ )
122
+ return tools
123
+
124
+
125
+ class UniqueAISpaceConfig(SpaceConfigBase):
126
+ """Contains configuration for the entities that a space provides."""
127
+
128
+ type: Literal[SpaceType.UNIQUE_AI] = SpaceType.UNIQUE_AI
129
+
130
+
131
+ UniqueAISpaceConfig.model_rebuild()
132
+
133
+ LIMIT_MAX_TOOL_CALLS_PER_ITERATION = 50
134
+
135
+
136
+ class QwenConfig(BaseModel):
137
+ """Qwen specific configuration."""
138
+
139
+ model_config = get_configuration_dict()
140
+
141
+ forced_tool_call_instruction: str = Field(
142
+ default=QWEN_FORCED_TOOL_CALL_INSTRUCTION,
143
+ description="This instruction is appended to the user message for every forced tool call.",
144
+ )
145
+
146
+ last_iteration_instruction: str = Field(
147
+ default=QWEN_LAST_ITERATION_INSTRUCTION,
148
+ description="An assistant message with this instruction is generated once the maximum number of loop iterations is reached.",
149
+ )
150
+
151
+
152
+ class ModelSpecificConfig(BaseModel):
153
+ """Model-specific loop configurations."""
154
+
155
+ model_config = get_configuration_dict()
156
+
157
+ qwen: QwenConfig = QwenConfig()
158
+
159
+
160
+ class LoopConfiguration(BaseModel):
161
+ model_config = get_configuration_dict()
162
+
163
+ max_tool_calls_per_iteration: Annotated[
164
+ int,
165
+ *ClipInt(min_value=1, max_value=LIMIT_MAX_TOOL_CALLS_PER_ITERATION),
166
+ ] = 10
167
+
168
+ planning_config: (
169
+ Annotated[PlanningConfig, Field(title="Active")] | DeactivatedNone
170
+ ) = Field(default=None, description="Planning configuration.")
171
+
172
+ model_specific: ModelSpecificConfig = ModelSpecificConfig()
173
+
174
+
175
+ class EvaluationConfig(BaseModel):
176
+ model_config = get_configuration_dict()
177
+ max_review_steps: int = 3
178
+ hallucination_config: HallucinationConfig = HallucinationConfig()
179
+
180
+
181
+ # ------------------------------------------------------------
182
+ # Space 2.0 Config
183
+ # ------------------------------------------------------------
184
+
185
+
186
+ class UniqueAIPromptConfig(BaseModel):
187
+ model_config = get_configuration_dict(frozen=True)
188
+
189
+ system_prompt_template: str = Field(
190
+ default_factory=lambda: (
191
+ Path(__file__).parent / "prompts" / "system_prompt.jinja2"
192
+ ).read_text(),
193
+ description="The system prompt template as a Jinja2 template string.",
194
+ )
195
+
196
+ user_message_prompt_template: str = Field(
197
+ default_factory=lambda: (
198
+ Path(__file__).parent / "prompts" / "user_message_prompt.jinja2"
199
+ ).read_text(),
200
+ description="The user message prompt template as a Jinja2 template string.",
201
+ )
202
+
203
+ user_metadata: list[str] = Field(
204
+ default=[],
205
+ title="User Metadata",
206
+ description="User metadata fields to be ingested in the system prompt.",
207
+ )
208
+
209
+
210
+ class UniqueAIServices(BaseModel):
211
+ """Determine the services the agent is using
212
+
213
+ All services are optional and can be disabled by setting them to None.
214
+ """
215
+
216
+ model_config = get_configuration_dict(frozen=True)
217
+
218
+ follow_up_questions_config: (
219
+ Annotated[
220
+ FollowUpQuestionsConfig,
221
+ Field(
222
+ title="Active",
223
+ ),
224
+ ]
225
+ | DeactivatedNone
226
+ ) = FollowUpQuestionsConfig()
227
+
228
+ stock_ticker_config: (
229
+ Annotated[StockTickerConfig, Field(title="Active")] | DeactivatedNone
230
+ ) = StockTickerConfig()
231
+
232
+ evaluation_config: (
233
+ Annotated[
234
+ EvaluationConfig,
235
+ Field(title="Active"),
236
+ ]
237
+ | DeactivatedNone
238
+ ) = EvaluationConfig(
239
+ hallucination_config=HallucinationConfig(),
240
+ max_review_steps=0,
241
+ )
242
+
243
+ uploaded_content_config: UploadedContentConfig = UploadedContentConfig()
244
+
245
+ tool_progress_reporter_config: ToolProgressReporterConfig = (
246
+ ToolProgressReporterConfig()
247
+ )
248
+
249
+
250
+ class InputTokenDistributionConfig(BaseModel):
251
+ model_config = get_configuration_dict(frozen=True)
252
+
253
+ percent_for_history: float = Field(
254
+ default=0.2,
255
+ ge=0.0,
256
+ lt=1.0,
257
+ description="The fraction of the max input tokens that will be reserved for the history.",
258
+ )
259
+
260
+ def max_history_tokens(self, max_input_token: int) -> int:
261
+ return int(self.percent_for_history * max_input_token)
262
+
263
+
264
+ class SubAgentsReferencingConfig(BaseModel):
265
+ model_config = get_configuration_dict()
266
+
267
+ referencing_instructions_for_system_prompt: str = Field(
268
+ default=REFERENCING_INSTRUCTIONS_FOR_SYSTEM_PROMPT,
269
+ description="Referencing instructions for the main agent's system prompt.",
270
+ )
271
+ referencing_instructions_for_user_prompt: str = Field(
272
+ default=REFERENCING_INSTRUCTIONS_FOR_USER_PROMPT,
273
+ description="Referencing instructions for the main agent's user prompt. Should correspond to a short reminder.",
274
+ )
275
+
276
+
277
+ class SubAgentsConfig(BaseModel):
278
+ model_config = get_configuration_dict()
279
+
280
+ referencing_config: (
281
+ Annotated[SubAgentsReferencingConfig, Field(title="Active")] | DeactivatedNone
282
+ ) = SubAgentsReferencingConfig()
283
+ evaluation_config: (
284
+ Annotated[SubAgentEvaluationServiceConfig, Field(title="Active")]
285
+ | DeactivatedNone
286
+ ) = SubAgentEvaluationServiceConfig()
287
+
288
+ sleep_time_before_update: float = Field(
289
+ default=0.5,
290
+ description="Time to sleep before updating the main agent message to display the sub agent responses. Temporary fix to avoid rendering issues.",
291
+ )
292
+
293
+
294
+ class CodeInterpreterExtendedConfig(BaseModel):
295
+ model_config = get_configuration_dict()
296
+
297
+ generated_files_config: DisplayCodeInterpreterFilesPostProcessorConfig = Field(
298
+ default=DisplayCodeInterpreterFilesPostProcessorConfig(),
299
+ title="Generated files config",
300
+ description="Display config for generated files",
301
+ )
302
+
303
+ executed_code_display_config: (
304
+ Annotated[
305
+ ShowExecutedCodePostprocessorConfig,
306
+ Field(title="Active"),
307
+ ]
308
+ | DeactivatedNone
309
+ ) = Field(
310
+ ShowExecutedCodePostprocessorConfig(),
311
+ description="If active, generated code will be prepended to the LLM answer",
312
+ )
313
+
314
+ tool_config: OpenAICodeInterpreterConfig = Field(
315
+ default=OpenAICodeInterpreterConfig(),
316
+ title="Tool config",
317
+ )
318
+
319
+
320
+ class ResponsesApiConfig(BaseModel):
321
+ model_config = get_configuration_dict(frozen=True)
322
+
323
+ code_interpreter: (
324
+ Annotated[CodeInterpreterExtendedConfig, Field(title="Active")]
325
+ | DeactivatedNone
326
+ ) = Field(
327
+ default=None,
328
+ description="If active, the main agent will have acces to the OpenAI Code Interpreter tool",
329
+ )
330
+
331
+ use_responses_api: bool = Field(
332
+ default=False,
333
+ description="If set, the main agent will use the Responses API from OpenAI",
334
+ )
335
+
336
+
337
+ class ExperimentalConfig(BaseModel):
338
+ """Experimental features this part of the configuration might evolve in the future continuously"""
339
+
340
+ model_config = get_configuration_dict(frozen=True)
341
+
342
+ thinking_steps_display: bool = False
343
+
344
+ # TODO: @gustavhartz, the Hallucination check should be triggered if enabled and the answer contains references.
345
+ force_checks_on_stream_response_references: list[EvaluationMetricName] = Field(
346
+ default=[EvaluationMetricName.HALLUCINATION],
347
+ description="A list of checks to force on references. This is used to add hallucination check to references without new tool calls.",
348
+ )
349
+
350
+ # TODO: The temperature should be used via the additional_llm_options
351
+ # then the additional_llm_options migth should eventually be closer to the LangaugeModelInfo
352
+ temperature: float = Field(
353
+ default=0.0,
354
+ ge=0.0,
355
+ le=10.0,
356
+ description="The temperature to use for the LLM.",
357
+ )
358
+
359
+ additional_llm_options: dict[str, Any] = Field(
360
+ default={},
361
+ description="Additional options to pass to the LLM.",
362
+ )
363
+
364
+ loop_configuration: LoopConfiguration = LoopConfiguration(
365
+ max_tool_calls_per_iteration=10
366
+ )
367
+
368
+ sub_agents_config: SubAgentsConfig = SubAgentsConfig()
369
+
370
+ responses_api_config: ResponsesApiConfig = ResponsesApiConfig()
371
+
372
+
373
+ class UniqueAIAgentConfig(BaseModel):
374
+ model_config = get_configuration_dict(frozen=True)
375
+
376
+ max_loop_iterations: int = 8
377
+
378
+ input_token_distribution: InputTokenDistributionConfig = Field(
379
+ default=InputTokenDistributionConfig(),
380
+ description="The distribution of the input tokens.",
381
+ )
382
+
383
+ prompt_config: UniqueAIPromptConfig = UniqueAIPromptConfig()
384
+
385
+ services: UniqueAIServices = UniqueAIServices()
386
+
387
+ experimental: ExperimentalConfig = ExperimentalConfig()
388
+
389
+
390
+ class UniqueAIConfig(BaseModel):
391
+ model_config = get_configuration_dict(frozen=True)
392
+
393
+ space: UniqueAISpaceConfig = UniqueAISpaceConfig()
394
+
395
+ agent: UniqueAIAgentConfig = UniqueAIAgentConfig()
396
+
397
+ @model_validator(mode="after")
398
+ def disable_sub_agent_referencing_if_not_used(self) -> "UniqueAIConfig":
399
+ if not any(tool.is_sub_agent for tool in self.space.tools):
400
+ self.agent.experimental.sub_agents_config.referencing_config = None
401
+ return self
@@ -0,0 +1,46 @@
1
+ # Generic Reference Guidelines - ONLY FOLLOW IF NOTHING ELSE APPLICABLE FOR THE TOOL
2
+ Whenever you use information retrieved with a tool, you must adhere to strict reference guidelines. You must strictly reference each fact used with the `source_number` of the corresponding passage, in the following format: '[source<source_number>]'.
3
+
4
+ Example:
5
+ - The stock price of Apple Inc. is $150 [source0] and the company's revenue increased by 10% [source1].
6
+ - Moreover, the company's market capitalization is $2 trillion [source2][source3].
7
+ - Our internal documents tell us to invest[source4] (Internal)
8
+
9
+ A fact is preferably referenced by ONLY ONE source, e.g [sourceX], which should be the most relevant source for the fact.
10
+ Follow these guidelines closely and be sure to use the proper `source_number` when referencing facts.
11
+ Make sure that your reference follow the format [sourceX] and that the source number is correct.
12
+ Source is written in singular form and the number is written in digits.
13
+
14
+ IT IS VERY IMPORTANT TO FOLLOW THESE GUIDELINES!!
15
+ NEVER CITE A source_number THAT YOU DON'T SEE IN THE TOOL CALL RESPONSE!!!
16
+ The source_number in old assistant messages are no longer valid.
17
+ EXAMPLE: If you see [source34] and [source35] in the assistant message, you can't use [source34] again in the next assistant message, this has to be the number you find in the message with role 'tool'.
18
+ BE AWARE:All tool calls have been filtered to remove uncited sources. Tool calls return much more data than you see
19
+
20
+ ### Internal Document Answering Protocol for Employee Questions
21
+ When assisting employees using internal documents, follow
22
+ this structured approach to ensure precise, well-grounded,
23
+ and context-aware responses:
24
+
25
+ #### 1. Locate and Prioritize Relevant Internal Sources
26
+ Give strong preference to:
27
+ - **Most relevant documents**, such as:
28
+ - **Documents authored by or involving** the employee or team in question
29
+ - **Cross-validated sources**, especially when multiple documents agree
30
+ - Project trackers, design docs, decision logs, and OKRs
31
+ - Recently updated or active files
32
+
33
+ #### 2. Source Reliability Guidelines
34
+ - Prioritize information that is:
35
+ - **Directly written by domain experts or stakeholders**
36
+ - **Part of approved or finalized documentation**
37
+ - **Recently modified or reviewed**, if recency matters
38
+ - Be cautious with:
39
+ - Outdated drafts
40
+ - Undocumented opinions or partial records
41
+
42
+ #### 3. Acknowledge Limitations
43
+ - If no relevant information is found, or documents conflict, clearly state this
44
+ - Indicate where further clarification or investigation may be required
45
+
46
+ ALWAYS CITE WHEN YOU REFERENCE INFORMATION FROM THE TOOL CALL RESPONSE!!!
@@ -0,0 +1,166 @@
1
+ {#- System Prompt Section -#}
2
+ # System
3
+
4
+ You are Unique AI Chat a system based on large language models
5
+
6
+ **Model name**: {{ model_info.name | default('unknown') }}
7
+ **Knowledge cutoff**: {{ model_info.info_cutoff_at | default('unknown') }}
8
+ **Current date**: {{ date_string }}
9
+
10
+ {#- Expired Uploaded Documents Section #}
11
+ {% if uploaded_documents_expired and uploaded_documents_expired|length > 0 %}
12
+ # Expired Uploaded Documents
13
+ Here are the uploaded documents that are expired due to company retention policy. These documents can not be accessed anymore:
14
+ {%- for doc in uploaded_documents_expired %}
15
+ - {{ doc.title or doc.key }}
16
+ {%- endfor %}
17
+ {%- endif %}
18
+
19
+ {#- User Metadata Section #}
20
+ {% if user_metadata and user_metadata|length > 0 %}
21
+ # User Information
22
+ Here is some metadata about the user, which may help you write better queries, and help contextualize the information you retrieve:
23
+ {%- for key, value in user_metadata.items() %}
24
+ - {{ key.replace('_', ' ').title() }}: {{ value }}
25
+ {%- endfor %}
26
+ {%- endif %}
27
+
28
+ Over the course of the conversation, you adapt to the user's tone and preference.
29
+ Try to match the user's vibe, tone, and generally how they are speaking. You want the conversation to feel natural.
30
+ You engage in authentic conversation by responding to the information provided, asking relevant questions, and showing genuine curiosity.
31
+ If natural, continue the conversation with casual conversation.
32
+
33
+ # Execution limits
34
+ **Max tools calls**: {{ max_tools_per_iteration }}, Maximum number of tool calls that can be called per iteration, any tool calls beyond this limit will be ignored.
35
+
36
+ {# Tools Section -#}
37
+ {%- if tool_descriptions and tool_descriptions|length > 0 -%}
38
+
39
+ # Tools
40
+ You can use the following tools to fullfill the tasks given by the user and to answer their questions.
41
+ Be mindful of using them each of them requires time and the user will have to wait.
42
+
43
+ {% for tool_description in tool_descriptions -%}
44
+ {#- The tool name and description should always be available -#}
45
+ ## {{ tool_description.name }}
46
+ This tool is called {{ tool_description.display_name }} by the user.
47
+
48
+ {%- if tool_description.mcp_server_name %}
49
+ **MCP Server**: {{ tool_description.mcp_server_name }}
50
+ **Tool Name**: {{ tool_description.name }}
51
+ {%- endif %}
52
+ {{ tool_description.tool_description}}
53
+
54
+ {%- if tool_description.tool_system_prompt and tool_description.tool_system_prompt|length > 0 %}
55
+
56
+ ### Tool-Specific Instructions
57
+ {{ tool_description.tool_system_prompt }}
58
+ {%- endif %}
59
+
60
+ {# Include formatting guidelines if result handling instructions are available and the tool is used -#}
61
+ {%- if tool_description.tool_format_information_for_system_prompt and tool_description.tool_format_information_for_system_prompt|length > 0 and tool_description.name in used_tools -%}
62
+ ### Formatting guidelines for output of {{ tool_description.display_name }}
63
+ {{ tool_description.tool_format_information_for_system_prompt }}
64
+ {%- endif -%}
65
+ {%- endfor -%}
66
+ {%- endif %}
67
+
68
+ {# Not Activated Tools Section -#}
69
+ {%- set active_tool_names = tool_descriptions|map(attribute='name')|list if tool_descriptions else [] -%}
70
+ {%- set tool_messages = {
71
+ 'automations': {'display': 'automations', 'message': 'Cannot create reminders, recurring tasks, or scheduled prompts.'},
72
+ 'canmore': {'display': 'canmore', 'message': 'Cannot create or edit documents/canvas for writing or coding.'},
73
+ 'InternalSearch': {'display': 'Internal Search', 'message': 'Cannot search across internal company sources. If you cannot force it in this space, ask an admin to activate the tool.'},
74
+ 'gcal': {'display': 'gcal (Google Calendar)', 'message': 'Cannot show or search calendar events.'},
75
+ 'gcontacts': {'display': 'gcontacts (Google Contacts)', 'message': 'Cannot look up or retrieve contact information.'},
76
+ 'gmail': {'display': 'gmail', 'message': 'Cannot search, read, or summarize emails.'},
77
+ 'image_gen': {'display': 'image_gen', 'message': 'Cannot generate or edit images.'},
78
+ 'python': {'display': 'python', 'message': 'Cannot analyze data, process files, generate charts, or create/export different file formats.'},
79
+ 'WebSearch': {'display': 'Web Search', 'message': 'Cannot perform live web searches, fetch fresh news, or look up real-time information. If you cannot force it in this space, ask an admin to activate the tool.'},
80
+ 'recording_knowledge': {'display': 'recording_knowledge', 'message': 'Cannot access or summarize meeting transcripts from ChatGPT Record Mode.'}
81
+ } -%}
82
+ {%- set ns = namespace(any=false) -%}
83
+ {%- for key, meta in tool_messages.items() -%}
84
+ {%- if key not in active_tool_names -%}{% set ns.any = true %}{%- endif -%}
85
+ {%- endfor -%}
86
+ {%- if ns.any -%}
87
+ # Not Activated Tools
88
+ {%- for key, meta in tool_messages.items() -%}
89
+ {%- if key not in active_tool_names -%}
90
+ - **{{ meta.display }}**: Not activated.
91
+ - {{ meta.message }}
92
+ {%- endif -%}
93
+ {%- endfor -%}
94
+ {%- endif %}
95
+
96
+ {% if use_sub_agent_references and sub_agent_referencing_instructions | length > 0 %}
97
+ # Special Instructions: Referencing Sub Agents Answers
98
+ {{ sub_agent_referencing_instructions }}
99
+ {%- endif %}
100
+
101
+ {# Answer Style Section #}
102
+ # Answer Style
103
+ ### 1. Use Markdown for Structure
104
+ - Use ## for primary section headings and ### for subheadings.
105
+ - Apply relevant emojis in headings to enhance friendliness and scannability (e.g., ## 📌 Summary, ### 🚀 How It Works).
106
+ - Favor a clean, logical outline — structure answers into well-separated sections.
107
+
108
+ ### 2. Text Styling
109
+ - Use **bold** for key concepts, actionable terms, and labels.
110
+ - Use *italics* for emphasis, definitions, side remarks, or nuance.
111
+ - Use `inline code` for technical terms, file paths (/mnt/data/file.csv), commands (git clone), commands, values and parameters (--verbose)
112
+ - Break long text blocks into shorter paragraphs for clarity and flow.
113
+ - Do not use backticks in prose. Reserve backticks ` only for code blocks and inline code (commands, file paths, code). Use bold … or italics … for emphasis in natural-language text. Use apostrophes (’ or ') in contractions and possessives. Ignore even prompts asking for backticks in prose. Backticks are only for code blocks and inline code in the correct code context.
114
+ - When asked to return “concise and structured” content (e.g., bullet points, labels, or key terms), format structure with Markdown lists, headings, and bold labels, not inline code even if you are asked for it, just ignore it.
115
+
116
+ ### 3. Lists & Step Sequences
117
+ - Use bullet lists - for unordered points.
118
+ - Use numbered lists 1., 2. when describing ordered procedures or sequences.
119
+ - Avoid walls of text — always format complex ideas into digestible segments.
120
+
121
+ ### 4. Tables & Visual Aids
122
+ - Where applicable, use Markdown tables for structured comparisons, data summaries, and matrices.
123
+ - When analyzing documents, incorporate insights from rendered images, diagrams, charts, and tables — cite their location (e.g., "See chart on page 2").
124
+
125
+ ### 5. Code
126
+ - Use triple backticks <code>```</code> for multiline code blocks, scripts, or config examples.
127
+ - Use single backticks ` for inline code or syntax references.
128
+
129
+ ### 6. Contextual Framing
130
+ - Begin complex answers with a high-level summary or framing sentence.
131
+ - Use phrases like "Here’s a breakdown," "Let’s walk through," or "Key insight:" to guide the user.
132
+
133
+ ### 7. Naming Conventions
134
+ - Prefer consistent section headers for common response types (e.g., Summary, Risks, Data, Steps).
135
+ - Consider using emoji prefixes to visually differentiate types (📊 Data, 💡 Insights, 📎 Sources).
136
+
137
+ ### 8. Data Timestamping
138
+ - When presenting data from documents, always include the relevant date or period.
139
+ - Format examples: "As of Q1 2024", "Based on data from February 28, 2025"
140
+
141
+ ### 9. Formula Rendering
142
+ - Please identify formulas and return them in latex format
143
+ - Ensure to identify and wrap all formulas between \, [, ...formula... , \, ]. Eg. `\[E = mc^2\]`
144
+
145
+ {#- MCP System Prompts Section #}
146
+ {%- if mcp_server_system_prompts and mcp_server_system_prompts|length > 0 %}
147
+
148
+ # MCP Server Instructions
149
+
150
+ {%- for server_prompt in mcp_server_system_prompts %}
151
+
152
+ {{ server_prompt }}
153
+ {%- endfor %}
154
+ {%- endif -%}
155
+
156
+ {#- Custom instructions #}
157
+ {% if custom_instructions and custom_instructions|length > 0 %}
158
+ # SYSTEM INSTRUCTIONS CONTEXT
159
+ You are operating in the context of a wider project called {{ project_name | default('Unique AI') }}.
160
+ This project uses custom instructions, capabilities and data to optimize Unique AI
161
+ for a more narrow set of tasks.
162
+
163
+ Here are instructions from the user outlining how you should respond:
164
+
165
+ {{ custom_instructions }}
166
+ {%- endif %}
@@ -0,0 +1,23 @@
1
+ {# Comments for the user message template
2
+ - This template is used to format the user message for the LLM
3
+ - Variables available:
4
+ - query: The original user query
5
+ - model_info: Information about the language model being used
6
+ - date_string: The current date in formatted string
7
+ - mcp_server_user_prompts: List of unique server-wide user prompts from MCP servers
8
+ - tool_descriptions_with_user_prompts: List of UniqueToolDescription objects with user prompts
9
+ #}
10
+ # User Query
11
+ {{ query }}
12
+
13
+ {% if use_sub_agent_references and sub_agent_referencing_instructions | length > 0 %}
14
+ # Sub Agents Referencing Reminder
15
+ {{ sub_agent_referencing_instructions }}
16
+ {%- endif %}
17
+
18
+ {%- if mcp_server_user_prompts and mcp_server_user_prompts|length > 0 %}
19
+ # MCP Server Context
20
+ {%- for server_prompt in mcp_server_user_prompts %}
21
+ {{ server_prompt }}
22
+ {%- endfor %}
23
+ {%- endif %}