Working!
This commit is contained in:
parent
10f28b0e9b
commit
8a4f94817a
@ -138,6 +138,7 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
|||||||
let filtered = [];
|
let filtered = [];
|
||||||
if (messageFilter === undefined) {
|
if (messageFilter === undefined) {
|
||||||
filtered = conversation;
|
filtered = conversation;
|
||||||
|
// console.log('No message filter provided. Using all messages.', filtered);
|
||||||
} else {
|
} else {
|
||||||
//console.log('Filtering conversation...')
|
//console.log('Filtering conversation...')
|
||||||
filtered = messageFilter(conversation); /* Do not copy conversation or useEffect will loop forever */
|
filtered = messageFilter(conversation); /* Do not copy conversation or useEffect will loop forever */
|
||||||
@ -402,7 +403,6 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const update = JSON.parse(line);
|
const update = JSON.parse(line);
|
||||||
console.log('Parsed update:', update.response);
|
|
||||||
|
|
||||||
switch (update.status) {
|
switch (update.status) {
|
||||||
case 'processing':
|
case 'processing':
|
||||||
@ -414,22 +414,24 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
|||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
break;
|
break;
|
||||||
case 'done':
|
case 'done':
|
||||||
|
console.log('Done processing:', update);
|
||||||
// Replace processing message with final result
|
// Replace processing message with final result
|
||||||
if (onResponse) {
|
if (onResponse) {
|
||||||
update.message = onResponse(update.response);
|
update.message = onResponse(update);
|
||||||
}
|
}
|
||||||
setProcessingMessage(undefined);
|
setProcessingMessage(undefined);
|
||||||
const backstoryMessage: BackstoryMessage = update.response;
|
const backstoryMessage: BackstoryMessage = update;
|
||||||
setConversation([
|
setConversation([
|
||||||
...conversationRef.current, {
|
...conversationRef.current, {
|
||||||
role: 'user',
|
// role: 'user',
|
||||||
content: backstoryMessage.prompt || "",
|
// content: backstoryMessage.prompt || "",
|
||||||
}, {
|
// }, {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
|
origin: type,
|
||||||
|
content: backstoryMessage.response || "",
|
||||||
prompt: backstoryMessage.prompt || "",
|
prompt: backstoryMessage.prompt || "",
|
||||||
preamble: backstoryMessage.preamble || {},
|
preamble: backstoryMessage.preamble || {},
|
||||||
full_content: backstoryMessage.full_content || "",
|
full_content: backstoryMessage.full_content || "",
|
||||||
content: backstoryMessage.response || "",
|
|
||||||
metadata: backstoryMessage.metadata,
|
metadata: backstoryMessage.metadata,
|
||||||
actions: backstoryMessage.actions,
|
actions: backstoryMessage.actions,
|
||||||
}] as MessageList);
|
}] as MessageList);
|
||||||
@ -485,21 +487,23 @@ const Conversation = forwardRef<ConversationHandle, ConversationProps>(({
|
|||||||
}, 5000);
|
}, 5000);
|
||||||
break;
|
break;
|
||||||
case 'done':
|
case 'done':
|
||||||
|
console.log('Done processing:', update);
|
||||||
if (onResponse) {
|
if (onResponse) {
|
||||||
update.message = onResponse(update.message);
|
update.message = onResponse(update);
|
||||||
}
|
}
|
||||||
setProcessingMessage(undefined);
|
setProcessingMessage(undefined);
|
||||||
const backstoryMessage: BackstoryMessage = update.message;
|
const backstoryMessage: BackstoryMessage = update;
|
||||||
setConversation([
|
setConversation([
|
||||||
...conversationRef.current, {
|
...conversationRef.current, {
|
||||||
role: 'user',
|
// role: 'user',
|
||||||
content: backstoryMessage.prompt || "",
|
// content: backstoryMessage.prompt || "",
|
||||||
}, {
|
// }, {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
|
origin: type,
|
||||||
prompt: backstoryMessage.prompt || "",
|
prompt: backstoryMessage.prompt || "",
|
||||||
|
content: backstoryMessage.response || "",
|
||||||
preamble: backstoryMessage.preamble || {},
|
preamble: backstoryMessage.preamble || {},
|
||||||
full_content: backstoryMessage.full_content || "",
|
full_content: backstoryMessage.full_content || "",
|
||||||
content: backstoryMessage.response || "",
|
|
||||||
metadata: backstoryMessage.metadata,
|
metadata: backstoryMessage.metadata,
|
||||||
actions: backstoryMessage.actions,
|
actions: backstoryMessage.actions,
|
||||||
}] as MessageList);
|
}] as MessageList);
|
||||||
|
@ -19,6 +19,7 @@ import Typography from '@mui/material/Typography';
|
|||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
import { ExpandMore } from './ExpandMore';
|
import { ExpandMore } from './ExpandMore';
|
||||||
import { SxProps, Theme } from '@mui/material';
|
import { SxProps, Theme } from '@mui/material';
|
||||||
|
import JsonView from '@uiw/react-json-view';
|
||||||
|
|
||||||
import { ChatBubble } from './ChatBubble';
|
import { ChatBubble } from './ChatBubble';
|
||||||
import { StyledMarkdown } from './StyledMarkdown';
|
import { StyledMarkdown } from './StyledMarkdown';
|
||||||
@ -182,7 +183,7 @@ const MessageMeta = (props: MessageMetaProps) => {
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
rag.map((rag: any) => (<>
|
rag.map((rag: any) => (
|
||||||
<Accordion key={rag.name}>
|
<Accordion key={rag.name}>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
<Box sx={{ fontSize: "0.8rem" }}>
|
<Box sx={{ fontSize: "0.8rem" }}>
|
||||||
@ -190,6 +191,10 @@ const MessageMeta = (props: MessageMetaProps) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
<AccordionDetails>
|
<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}>
|
{rag.ids.map((id: number, index: number) => <Box key={index}>
|
||||||
{index !== 0 && <Divider />}
|
{index !== 0 && <Divider />}
|
||||||
<Box sx={{ fontSize: "0.75rem", display: "flex", flexDirection: "row", mb: 0.5, mt: 0.5 }}>
|
<Box sx={{ fontSize: "0.75rem", display: "flex", flexDirection: "row", mb: 0.5, mt: 0.5 }}>
|
||||||
@ -205,54 +210,33 @@ const MessageMeta = (props: MessageMetaProps) => {
|
|||||||
)}
|
)}
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</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: '🔍',
|
query: '🔍',
|
||||||
resume: '📄',
|
resume: '📄',
|
||||||
projects: '📁',
|
projects: '📁',
|
||||||
|
jobs: '📁',
|
||||||
'performance-reviews': '📄',
|
'performance-reviews': '📄',
|
||||||
news: '📰',
|
news: '📰',
|
||||||
};
|
};
|
||||||
@ -91,7 +92,8 @@ const colorMap: Record<string, string> = {
|
|||||||
resume: '#4A7A7D', // Dusty Teal — secondary theme color
|
resume: '#4A7A7D', // Dusty Teal — secondary theme color
|
||||||
projects: '#1A2536', // Midnight Blue — rich and deep
|
projects: '#1A2536', // Midnight Blue — rich and deep
|
||||||
news: '#D3CDBF', // Warm Gray — soft and neutral
|
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> = {
|
const sizeMap: Record<string, number> = {
|
||||||
@ -156,7 +158,7 @@ const VectorVisualizer: React.FC<VectorVisualizerProps> = (props: VectorVisualiz
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!result || !result.embeddings) return;
|
if (!result || !result.embeddings) return;
|
||||||
if (result.embeddings.length === 0) return;
|
if (result.embeddings.length === 0) return;
|
||||||
|
console.log('Result:', result);
|
||||||
const vectors: (number[])[] = [...result.embeddings];
|
const vectors: (number[])[] = [...result.embeddings];
|
||||||
const documents = [...result.documents || []];
|
const documents = [...result.documents || []];
|
||||||
const metadatas = [...result.metadatas || []];
|
const metadatas = [...result.metadatas || []];
|
||||||
|
@ -413,6 +413,8 @@ class WebServer:
|
|||||||
|
|
||||||
dimensions = data.get("dimensions", 2)
|
dimensions = data.get("dimensions", 2)
|
||||||
result = self.file_watcher.umap_collection
|
result = self.file_watcher.umap_collection
|
||||||
|
if not result:
|
||||||
|
return JSONResponse({"error": "No UMAP collection found"}, status_code=404)
|
||||||
if dimensions == 2:
|
if dimensions == 2:
|
||||||
logger.info("Returning 2D UMAP")
|
logger.info("Returning 2D UMAP")
|
||||||
umap_embedding = self.file_watcher.umap_embedding_2d
|
umap_embedding = self.file_watcher.umap_embedding_2d
|
||||||
@ -420,6 +422,9 @@ class WebServer:
|
|||||||
logger.info("Returning 3D UMAP")
|
logger.info("Returning 3D UMAP")
|
||||||
umap_embedding = self.file_watcher.umap_embedding_3d
|
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()
|
result["embeddings"] = umap_embedding.tolist()
|
||||||
|
|
||||||
return JSONResponse(result)
|
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:
|
if not self.context:
|
||||||
raise ValueError("Context is not set for this agent.")
|
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()):
|
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}"
|
message.full_content += f"{message.prompt}"
|
||||||
|
|
||||||
# Estimate token length of new messages
|
# 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_size = chunk_size
|
||||||
self.chunk_overlap = chunk_overlap
|
self.chunk_overlap = chunk_overlap
|
||||||
self.loop = loop
|
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.md = MarkItDown(enable_plugins=False) # Set to True to enable plugins
|
||||||
|
|
||||||
#self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
|
#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