Working!
This commit is contained in:
parent
10f28b0e9b
commit
8a4f94817a
@ -138,6 +138,7 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
||||
let filtered = [];
|
||||
if (messageFilter === undefined) {
|
||||
filtered = conversation;
|
||||
// console.log('No message filter provided. Using all messages.', filtered);
|
||||
} else {
|
||||
//console.log('Filtering conversation...')
|
||||
filtered = messageFilter(conversation); /* Do not copy conversation or useEffect will loop forever */
|
||||
@ -402,7 +403,6 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
||||
|
||||
try {
|
||||
const update = JSON.parse(line);
|
||||
console.log('Parsed update:', update.response);
|
||||
|
||||
switch (update.status) {
|
||||
case 'processing':
|
||||
@ -414,22 +414,24 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
break;
|
||||
case 'done':
|
||||
console.log('Done processing:', update);
|
||||
// Replace processing message with final result
|
||||
if (onResponse) {
|
||||
update.message = onResponse(update.response);
|
||||
update.message = onResponse(update);
|
||||
}
|
||||
setProcessingMessage(undefined);
|
||||
const backstoryMessage: BackstoryMessage = update.response;
|
||||
const backstoryMessage: BackstoryMessage = update;
|
||||
setConversation([
|
||||
...conversationRef.current, {
|
||||
role: 'user',
|
||||
content: backstoryMessage.prompt || "",
|
||||
}, {
|
||||
// role: 'user',
|
||||
// content: backstoryMessage.prompt || "",
|
||||
// }, {
|
||||
role: 'assistant',
|
||||
origin: type,
|
||||
content: backstoryMessage.response || "",
|
||||
prompt: backstoryMessage.prompt || "",
|
||||
preamble: backstoryMessage.preamble || {},
|
||||
full_content: backstoryMessage.full_content || "",
|
||||
content: backstoryMessage.response || "",
|
||||
metadata: backstoryMessage.metadata,
|
||||
actions: backstoryMessage.actions,
|
||||
}] as MessageList);
|
||||
@ -485,21 +487,23 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
||||
}, 5000);
|
||||
break;
|
||||
case 'done':
|
||||
console.log('Done processing:', update);
|
||||
if (onResponse) {
|
||||
update.message = onResponse(update.message);
|
||||
update.message = onResponse(update);
|
||||
}
|
||||
setProcessingMessage(undefined);
|
||||
const backstoryMessage: BackstoryMessage = update.message;
|
||||
const backstoryMessage: BackstoryMessage = update;
|
||||
setConversation([
|
||||
...conversationRef.current, {
|
||||
role: 'user',
|
||||
content: backstoryMessage.prompt || "",
|
||||
}, {
|
||||
// role: 'user',
|
||||
// content: backstoryMessage.prompt || "",
|
||||
// }, {
|
||||
role: 'assistant',
|
||||
origin: type,
|
||||
prompt: backstoryMessage.prompt || "",
|
||||
content: backstoryMessage.response || "",
|
||||
preamble: backstoryMessage.preamble || {},
|
||||
full_content: backstoryMessage.full_content || "",
|
||||
content: backstoryMessage.response || "",
|
||||
metadata: backstoryMessage.metadata,
|
||||
actions: backstoryMessage.actions,
|
||||
}] as MessageList);
|
||||
|
@ -19,6 +19,7 @@ import Typography from '@mui/material/Typography';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import { ExpandMore } from './ExpandMore';
|
||||
import { SxProps, Theme } from '@mui/material';
|
||||
import JsonView from '@uiw/react-json-view';
|
||||
|
||||
import { ChatBubble } from './ChatBubble';
|
||||
import { StyledMarkdown } from './StyledMarkdown';
|
||||
@ -182,7 +183,7 @@ const MessageMeta = (props: MessageMetaProps) => {
|
||||
</Accordion>
|
||||
}
|
||||
{
|
||||
rag.map((rag: any) => (<>
|
||||
rag.map((rag: any) => (
|
||||
<Accordion key={rag.name}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box sx={{ fontSize: "0.8rem" }}>
|
||||
@ -190,6 +191,10 @@ const MessageMeta = (props: MessageMetaProps) => {
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Box sx={{ fontSize: "0.8rem" }}>
|
||||
UMAP Vector Visualization of '{rag.name}' RAG
|
||||
</Box>
|
||||
<VectorVisualizer inline {...props.messageProps} {...props.metadata} rag={rag} />
|
||||
{rag.ids.map((id: number, index: number) => <Box key={index}>
|
||||
{index !== 0 && <Divider />}
|
||||
<Box sx={{ fontSize: "0.75rem", display: "flex", flexDirection: "row", mb: 0.5, mt: 0.5 }}>
|
||||
@ -205,54 +210,33 @@ const MessageMeta = (props: MessageMetaProps) => {
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box sx={{ fontSize: "0.8rem" }}>
|
||||
UMAP Vector Visualization of RAG
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<VectorVisualizer inline {...message} {...props.metadata} rag={rag} />
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box sx={{ fontSize: "0.8rem" }}>
|
||||
All response fields
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{Object.entries(message)
|
||||
.filter(([key, value]) => key !== undefined && value !== undefined)
|
||||
.map(([key, value]) => (typeof (value) !== "string" || value?.trim() !== "") &&
|
||||
<Accordion key={key}>
|
||||
<AccordionSummary sx={{ fontSize: "1rem", fontWeight: "bold" }} expandIcon={<ExpandMoreIcon />}>
|
||||
{key}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{key === "metadata" &&
|
||||
Object.entries(value)
|
||||
.filter(([key, value]) => key !== undefined && value !== undefined)
|
||||
.map(([key, value]) => (
|
||||
<Accordion key={`metadata.${key}`}>
|
||||
<AccordionSummary sx={{ fontSize: "1rem", fontWeight: "bold" }} expandIcon={<ExpandMoreIcon />}>
|
||||
{key}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<pre>{`${typeof (value) !== "object" ? value : JSON.stringify(value)}`}</pre>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
))}
|
||||
{key !== "metadata" &&
|
||||
<pre>{typeof (value) !== "object" ? value : JSON.stringify(value)}</pre>
|
||||
}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</>))
|
||||
))
|
||||
}
|
||||
|
||||
<Accordion>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box sx={{ fontSize: "0.8rem" }}>
|
||||
All response fields
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{Object.entries(message)
|
||||
.filter(([key, value]) => key !== undefined && value !== undefined)
|
||||
.map(([key, value]) => (typeof (value) !== "string" || value?.trim() !== "") &&
|
||||
<Accordion key={key}>
|
||||
<AccordionSummary sx={{ fontSize: "1rem", fontWeight: "bold" }} expandIcon={<ExpandMoreIcon />}>
|
||||
{key}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{typeof (value) === "string" ?
|
||||
<pre>{value}</pre> :
|
||||
<JsonView collapsed={1} value={value as any} style={{ fontSize: "0.8rem", maxHeight: "20rem", overflow: "auto" }} />
|
||||
}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</>);
|
||||
};
|
||||
|
||||
|
@ -82,6 +82,7 @@ const emojiMap: Record<string, string> = {
|
||||
query: '🔍',
|
||||
resume: '📄',
|
||||
projects: '📁',
|
||||
jobs: '📁',
|
||||
'performance-reviews': '📄',
|
||||
news: '📰',
|
||||
};
|
||||
@ -91,7 +92,8 @@ const colorMap: Record<string, string> = {
|
||||
resume: '#4A7A7D', // Dusty Teal — secondary theme color
|
||||
projects: '#1A2536', // Midnight Blue — rich and deep
|
||||
news: '#D3CDBF', // Warm Gray — soft and neutral
|
||||
'performance-reviews': '#FF0000', // Bright red
|
||||
'performance-reviews': '#FFD0D0', // Light red
|
||||
'jobs': '#F3aD8F', // Warm Gray — soft and neutral
|
||||
};
|
||||
|
||||
const sizeMap: Record<string, number> = {
|
||||
@ -156,7 +158,7 @@ const VectorVisualizer: React.FC<VectorVisualizerProps> = (props: VectorVisualiz
|
||||
useEffect(() => {
|
||||
if (!result || !result.embeddings) return;
|
||||
if (result.embeddings.length === 0) return;
|
||||
|
||||
console.log('Result:', result);
|
||||
const vectors: (number[])[] = [...result.embeddings];
|
||||
const documents = [...result.documents || []];
|
||||
const metadatas = [...result.metadatas || []];
|
||||
|
@ -413,6 +413,8 @@ class WebServer:
|
||||
|
||||
dimensions = data.get("dimensions", 2)
|
||||
result = self.file_watcher.umap_collection
|
||||
if not result:
|
||||
return JSONResponse({"error": "No UMAP collection found"}, status_code=404)
|
||||
if dimensions == 2:
|
||||
logger.info("Returning 2D UMAP")
|
||||
umap_embedding = self.file_watcher.umap_embedding_2d
|
||||
@ -420,6 +422,9 @@ class WebServer:
|
||||
logger.info("Returning 3D UMAP")
|
||||
umap_embedding = self.file_watcher.umap_embedding_3d
|
||||
|
||||
if len(umap_embedding) == 0:
|
||||
return JSONResponse({"error": "No UMAP embedding found"}, status_code=404)
|
||||
|
||||
result["embeddings"] = umap_embedding.tolist()
|
||||
|
||||
return JSONResponse(result)
|
||||
|
43
src/utils/agents/__init__.py
Normal file
43
src/utils/agents/__init__.py
Normal file
@ -0,0 +1,43 @@
|
||||
from __future__ import annotations
|
||||
import importlib
|
||||
import pathlib
|
||||
import inspect
|
||||
import logging
|
||||
from typing import TypeAlias, Dict, Tuple
|
||||
from pydantic import BaseModel
|
||||
from . base import Agent
|
||||
|
||||
# Type alias for Agent or any subclass
|
||||
AnyAgent: TypeAlias = Agent # BaseModel covers Agent and subclasses
|
||||
|
||||
package_dir = pathlib.Path(__file__).parent
|
||||
package_name = __name__
|
||||
__all__ = []
|
||||
class_registry: Dict[str, Tuple[str, str]] = {} # Maps class_name to (module_name, class_name)
|
||||
|
||||
for path in package_dir.glob("*.py"):
|
||||
if path.name in ("__init__.py", "base.py") or path.name.startswith("_"):
|
||||
continue
|
||||
|
||||
module_name = path.stem
|
||||
full_module_name = f"{package_name}.{module_name}"
|
||||
|
||||
try:
|
||||
module = importlib.import_module(full_module_name)
|
||||
|
||||
# Find all Agent subclasses in the module
|
||||
for name, obj in inspect.getmembers(module, inspect.isclass):
|
||||
if (
|
||||
issubclass(obj, AnyAgent)
|
||||
and obj is not AnyAgent
|
||||
and obj is not Agent
|
||||
and name not in class_registry
|
||||
):
|
||||
class_registry[name] = (full_module_name, name)
|
||||
globals()[name] = obj
|
||||
logging.info(f"Adding agent: {name} from {full_module_name}")
|
||||
__all__.append(name)
|
||||
except ImportError as e:
|
||||
logging.error(f"Failed to import module {full_module_name}: {e}")
|
||||
|
||||
__all__.append("AnyAgent")
|
@ -203,9 +203,9 @@ class Chat(Agent, ABC):
|
||||
if not self.context:
|
||||
raise ValueError("Context is not set for this agent.")
|
||||
|
||||
message.full_content = ""
|
||||
message.full_content = f"<|system|>{self.system_prompt.strip()}\n"
|
||||
for i, p in enumerate(message.preamble.keys()):
|
||||
message.full_content += '' if i == 0 else '\n\n' + f"<|{p}|>{message.preamble[p].strip()}\n"
|
||||
message.full_content += f"\n<|{p}|>\n{message.preamble[p].strip()}\n"
|
||||
message.full_content += f"{message.prompt}"
|
||||
|
||||
# Estimate token length of new messages
|
||||
|
38
src/utils/agents/types.py
Normal file
38
src/utils/agents/types.py
Normal file
@ -0,0 +1,38 @@
|
||||
from __future__ import annotations
|
||||
from typing import List, Dict, Any, Union, ForwardRef, TypeVar, Optional, TYPE_CHECKING, Type, ClassVar, Literal
|
||||
from typing_extensions import Annotated
|
||||
from pydantic import Field, BaseModel
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
# Forward references
|
||||
AgentRef = ForwardRef('Agent')
|
||||
ContextRef = ForwardRef('Context')
|
||||
|
||||
# We'll use a registry pattern rather than hardcoded strings
|
||||
class AgentRegistry:
|
||||
"""Registry for agent types and classes"""
|
||||
_registry: Dict[str, Type] = {}
|
||||
|
||||
@classmethod
|
||||
def register(cls, agent_type: str, agent_class: Type) -> Type:
|
||||
"""Register an agent class with its type"""
|
||||
cls._registry[agent_type] = agent_class
|
||||
return agent_class
|
||||
|
||||
@classmethod
|
||||
def get_class(cls, agent_type: str) -> Optional[Type]:
|
||||
"""Get the class for a given agent type"""
|
||||
return cls._registry.get(agent_type)
|
||||
|
||||
@classmethod
|
||||
def get_types(cls) -> List[str]:
|
||||
"""Get all registered agent types"""
|
||||
return list(cls._registry.keys())
|
||||
|
||||
@classmethod
|
||||
def get_classes(cls) -> Dict[str, Type]:
|
||||
"""Get all registered agent classes"""
|
||||
return cls._registry.copy()
|
||||
|
||||
# Create a singleton instance
|
||||
registry = AgentRegistry()
|
@ -52,8 +52,12 @@ class ChromaDBFileWatcher(FileSystemEventHandler):
|
||||
self.chunk_size = chunk_size
|
||||
self.chunk_overlap = chunk_overlap
|
||||
self.loop = loop
|
||||
|
||||
|
||||
self._umap_collection = None
|
||||
self._umap_embedding_2d = []
|
||||
self._umap_embedding_3d = []
|
||||
self._umap_model_2d = None
|
||||
self._umap_model_3d = None
|
||||
self._collection = None
|
||||
self.md = MarkItDown(enable_plugins=False) # Set to True to enable plugins
|
||||
|
||||
#self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
|
||||
|
32
src/utils/setup_logging.py
Normal file
32
src/utils/setup_logging.py
Normal file
@ -0,0 +1,32 @@
|
||||
import os
|
||||
import warnings
|
||||
import logging
|
||||
|
||||
from . import defines
|
||||
|
||||
def setup_logging(level=defines.logging_level) -> logging.Logger:
|
||||
os.environ["TORCH_CPP_LOG_LEVEL"] = "ERROR"
|
||||
warnings.filterwarnings("ignore", message="Overriding a previously registered kernel")
|
||||
warnings.filterwarnings("ignore", message="Warning only once for all operators")
|
||||
warnings.filterwarnings("ignore", message="Couldn't find ffmpeg or avconv")
|
||||
warnings.filterwarnings("ignore", message="'force_all_finite' was renamed to")
|
||||
warnings.filterwarnings("ignore", message="n_jobs value 1 overridden")
|
||||
|
||||
numeric_level = getattr(logging, level.upper(), None)
|
||||
if not isinstance(numeric_level, int):
|
||||
raise ValueError(f"Invalid log level: {level}")
|
||||
|
||||
logging.basicConfig(
|
||||
level=numeric_level,
|
||||
format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
force=True
|
||||
)
|
||||
|
||||
# Now reduce verbosity for FastAPI, Uvicorn, Starlette
|
||||
for noisy_logger in ("uvicorn", "uvicorn.error", "uvicorn.access", "fastapi", "starlette"):
|
||||
logging.getLogger(noisy_logger).setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
return logger
|
Loading…
x
Reference in New Issue
Block a user