Compare commits

...

2 Commits

Author SHA1 Message Date
bb84709f44 Misc tweaks to prompt 2025-06-01 15:59:10 -07:00
c07510c525 Chat is working again 2025-06-01 14:39:42 -07:00
3 changed files with 30 additions and 58 deletions

View File

@ -358,8 +358,9 @@ class Agent(BaseModel, ABC):
size=user.file_watcher.collection.count() size=user.file_watcher.collection.count()
) )
entries += len(rag_metadata.documents)
rag_message.metadata.rag_results.append(rag_metadata) rag_message.metadata.rag_results.append(rag_metadata)
rag_message.content = f"Results from {rag.name} RAG: {len(chroma_results['documents'])} results." rag_message.content = f"Results from {rag.name} RAG: {len(rag_metadata.documents)} results."
yield rag_message yield rag_message
rag_message.content = ( rag_message.content = (
@ -377,7 +378,7 @@ class Agent(BaseModel, ABC):
return return
async def generate( async def generate(
self, llm: Any, model: str, user_message: ChatMessageUser, user_id: str, temperature=0.7 self, llm: Any, model: str, user_message: ChatMessageUser, user: Candidate, temperature=0.7
) -> AsyncGenerator[ChatMessage | ChatMessageBase, None]: ) -> AsyncGenerator[ChatMessage | ChatMessageBase, None]:
logger.info(f"{self.agent_type} - {inspect.stack()[0].function}") logger.info(f"{self.agent_type} - {inspect.stack()[0].function}")
@ -446,7 +447,7 @@ Content: { content }
messages.append( messages.append(
LLMMessage( LLMMessage(
role="user", role="user",
content=f"<|context|>\n{rag_context.strip()}\n</|context|>\n\n{user_message.content.strip()}\n" content=f"<|context|>\n{rag_context.strip()}\n</|context|>\n\nPrompt to respond to:\n{user_message.content.strip()}\n"
) )
) )
else: else:

View File

@ -7,44 +7,20 @@ from .base import Agent, agent_registry
from logger import logger from logger import logger
from .registry import agent_registry from .registry import agent_registry
from models import ( ChatQuery, ChatMessage, Tunables, ChatStatusType) from models import ( ChatQuery, ChatMessage, Tunables, ChatStatusType, ChatMessageUser, Candidate)
system_message = f""" system_message = f"""
Launched on {datetime.now().isoformat()}.
When answering queries, follow these steps: When answering queries, follow these steps:
- First analyze the query to determine if real-time information from the tools might be helpful - When any content from <|context|> is relevant, synthesize information from all sources to provide the most complete answer.
- Even when <|context|> or <|resume|> is provided, consider whether the tools would provide more current or comprehensive information - Always prioritize the most up-to-date, recent, and relevant information first.
- Use the provided tools whenever they would enhance your response, regardless of whether context is also available - If there is information in the <|context|> section to enhance the answer, incorporate it seamlessly and refer to it as 'the latest information' or 'recent data' instead of mentioning '<|context|>' (etc.) or quoting it directly.
- When presenting weather forecasts, include relevant emojis immediately before the corresponding text. For example, for a sunny day, say \"☀️ Sunny\" or if the forecast says there will be \"rain showers, say \"🌧️ Rain showers\". Use this mapping for weather emojis: Sunny: ☀️, Cloudy: ☁️, Rainy: 🌧️, Snowy: ❄️ - Avoid phrases like 'According to the <|context|>' or similar references to the <|context|>.
- When any combination of <|context|>, <|resume|> and tool outputs are relevant, synthesize information from all sources to provide the most complete answer
- Always prioritize the most up-to-date and relevant information, whether it comes from <|context|>, <|resume|> or tools
- If <|context|> and tool outputs contain conflicting information, prefer the tool outputs as they likely represent more current data
- If there is information in the <|context|> or <|resume|> sections to enhance the answer, incorporate it seamlessly and refer to it as 'the latest information' or 'recent data' instead of mentioning '<|context|>' (etc.) or quoting it directly.
- Avoid phrases like 'According to the <|context|>' or similar references to the <|context|> or <|resume|>.
CRITICAL INSTRUCTIONS FOR IMAGE GENERATION: Always <|context|> when possible. Be concise, and never make up information. If you do not know the answer, say so.
1. When the user requests to generate an image, inject the following into the response: <GenerateImage prompt="USER-PROMPT"/>. Do this when users request images, drawings, or visual content. Before answering, ensure you have spelled the candidate's name correctly.
3. MANDATORY: You must respond with EXACTLY this format: <GenerateImage prompt="{{USER-PROMPT}}"/>
4. FORBIDDEN: DO NOT use markdown image syntax ![](url)
5. FORBIDDEN: DO NOT create fake URLs or file paths
6. FORBIDDEN: DO NOT use any other image embedding format
CORRECT EXAMPLE:
User: "Draw a cat"
Your response: "<GenerateImage prompt='Draw a cat'/>"
WRONG EXAMPLES (DO NOT DO THIS):
- ![](https://example.com/...)
- ![Cat image](any_url)
- <img src="...">
The <GenerateImage prompt="{{USER-PROMPT}}"/> format is the ONLY way to display images in this system.
DO NOT make up a URL for an image or provide markdown syntax for embedding an image. Only use <GenerateImage prompt="{{USER-PROMPT}}".
Always use tools, <|resume|>, and <|context|> when possible. Be concise, and never make up information. If you do not know the answer, say so.
""" """
class CandidateChat(Agent): class CandidateChat(Agent):
@ -57,31 +33,26 @@ class CandidateChat(Agent):
system_prompt: str = system_message system_prompt: str = system_message
# async def prepare_message(self, message: Message) -> AsyncGenerator[Message, None]: async def generate(
# logger.info(f"{self.agent_type} - {inspect.stack()[0].function}") self, llm: Any, model: str, user_message: ChatMessageUser, user: Candidate, temperature=0.7
# if not self.context: ):
# raise ValueError("Context is not set for this agent.") self.system_prompt = f"""
You are a helpful expert system representing a {user.first_name}'s work history to potential employers and users curious about the candidate. You want to incorporate as many facts and details about {user.first_name} as possible.
# async for message in super().prepare_message(message): When referencing the candidate, ALWAYS ensure correct spelling.
# if message.status != "done":
# yield message
# if message.preamble: The candidate's first name is: "{user.first_name}"
# excluded = {} The candidate's last name is: "{user.last_name}"
# preamble_types = [
# f"<|{p}|>" for p in message.preamble.keys() if p not in excluded
# ]
# preamble_types_AND = " and ".join(preamble_types)
# preamble_types_OR = " or ".join(preamble_types)
# message.preamble[
# "rules"
# ] = f"""\
# - Answer the question based on the information provided in the {preamble_types_AND} sections by incorporate it seamlessly and refer to it using natural language instead of mentioning {preamble_types_OR} or quoting it directly.
# - If there is no information in these sections, answer based on your knowledge, or use any available tools.
# - Avoid phrases like 'According to the {preamble_types[0]}' or similar references to the {preamble_types_OR}.
# """
# message.preamble["question"] = "Respond to:"
Use that spelling instead of any spelling you may find in the <|context|>.
{system_message}
"""
async for message in super().generate(llm, model, user_message, user, temperature):
yield message
# Register the base agent # Register the base agent
agent_registry.register(CandidateChat._agent_type, CandidateChat) agent_registry.register(CandidateChat._agent_type, CandidateChat)

View File

@ -1994,7 +1994,7 @@ async def post_chat_session_message_stream(
llm=llm_manager.get_llm(), llm=llm_manager.get_llm(),
model=defines.model, model=defines.model,
user_message=user_message, user_message=user_message,
user_id=current_user.id, user=current_user,
): ):
# Store reference to the complete AI message # Store reference to the complete AI message
if generated_message.status == ChatStatusType.DONE: if generated_message.status == ChatStatusType.DONE: