new names

This commit is contained in:
Nicolò Boschi 2025-12-04 21:34:05 +01:00
parent 718b702877
commit 06b956a553
67 changed files with 798 additions and 764 deletions

View file

@ -35,6 +35,7 @@ docker run -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight
```

View file

@ -31,7 +31,7 @@ def upgrade() -> None:
'banks',
sa.Column('bank_id', sa.Text(), nullable=False),
sa.Column('name', sa.Text(), nullable=True),
sa.Column('personality', postgresql.JSONB(astext_type=sa.Text()), server_default=sa.text("'{}'::jsonb"), nullable=False),
sa.Column('disposition', postgresql.JSONB(astext_type=sa.Text()), server_default=sa.text("'{}'::jsonb"), nullable=False),
sa.Column('background', sa.Text(), nullable=True),
sa.Column('created_at', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('updated_at', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False),

View file

@ -1,4 +1,4 @@
"""Rename fact_type 'bank' to 'interactions'
"""Rename fact_type 'bank' to 'experience'
Revision ID: d9f6a3b4c5e2
Revises: c8e5f2a3b4d1
@ -20,14 +20,16 @@ def upgrade():
# Drop old check constraint FIRST (before updating data)
op.drop_constraint('memory_units_fact_type_check', 'memory_units', type_='check')
# Update existing 'bank' values to 'interactions'
op.execute("UPDATE memory_units SET fact_type = 'interactions' WHERE fact_type = 'bank'")
# Update existing 'bank' values to 'experience'
op.execute("UPDATE memory_units SET fact_type = 'experience' WHERE fact_type = 'bank'")
# Also update any 'interactions' values (in case of partial migration)
op.execute("UPDATE memory_units SET fact_type = 'experience' WHERE fact_type = 'interactions'")
# Create new check constraint with 'interactions' instead of 'bank'
# Create new check constraint with 'experience' instead of 'bank'
op.create_check_constraint(
'memory_units_fact_type_check',
'memory_units',
"fact_type IN ('world', 'interactions', 'opinion', 'observation')"
"fact_type IN ('world', 'experience', 'opinion', 'observation')"
)
@ -35,8 +37,8 @@ def downgrade():
# Drop new check constraint FIRST
op.drop_constraint('memory_units_fact_type_check', 'memory_units', type_='check')
# Update 'interactions' back to 'bank'
op.execute("UPDATE memory_units SET fact_type = 'bank' WHERE fact_type = 'interactions'")
# Update 'experience' back to 'bank'
op.execute("UPDATE memory_units SET fact_type = 'bank' WHERE fact_type = 'experience'")
# Recreate old check constraint
op.create_check_constraint(

View file

@ -87,7 +87,7 @@ from .http import (
ReflectRequest,
ReflectResponse,
CreateBankRequest,
PersonalityTraits,
DispositionTraits,
)
__all__ = [
@ -100,5 +100,5 @@ __all__ = [
"ReflectRequest",
"ReflectResponse",
"CreateBankRequest",
"PersonalityTraits",
"DispositionTraits",
]

View file

@ -84,7 +84,7 @@ class RecallRequest(BaseModel):
model_config = ConfigDict(json_schema_extra={
"example": {
"query": "What did Alice say about machine learning?",
"types": ["world", "interactions"],
"types": ["world", "experience"],
"budget": "mid",
"max_tokens": 4096,
"trace": True,
@ -131,7 +131,7 @@ class RecallResult(BaseModel):
id: str
text: str
type: Optional[str] = None # fact type: world, interactions, opinion, observation
type: Optional[str] = None # fact type: world, experience, opinion, observation
entities: Optional[List[str]] = None # Entity names mentioned in this fact
context: Optional[str] = None
occurred_start: Optional[str] = None # ISO format date when the event started
@ -397,7 +397,7 @@ class ReflectFact(BaseModel):
id: Optional[str] = None
text: str
type: Optional[str] = None # fact type: world, interactions, opinion
type: Optional[str] = None # fact type: world, experience, opinion
context: Optional[str] = None
occurred_start: Optional[str] = None
occurred_end: Optional[str] = None
@ -417,7 +417,7 @@ class ReflectResponse(BaseModel):
{
"id": "456",
"text": "I discussed AI applications last week",
"type": "interactions"
"type": "experience"
}
]
}
@ -438,8 +438,8 @@ class BanksResponse(BaseModel):
banks: List[str]
class PersonalityTraits(BaseModel):
"""Personality traits based on Big Five model."""
class DispositionTraits(BaseModel):
"""Disposition traits based on Big Five model."""
model_config = ConfigDict(json_schema_extra={
"example": {
"openness": 0.8,
@ -456,7 +456,7 @@ class PersonalityTraits(BaseModel):
extraversion: float = Field(ge=0.0, le=1.0, description="Extraversion (0-1)")
agreeableness: float = Field(ge=0.0, le=1.0, description="Agreeableness (0-1)")
neuroticism: float = Field(ge=0.0, le=1.0, description="Neuroticism (0-1)")
bias_strength: float = Field(ge=0.0, le=1.0, description="How strongly personality influences opinions (0-1)")
bias_strength: float = Field(ge=0.0, le=1.0, description="How strongly disposition influences opinions (0-1)")
class BankProfileResponse(BaseModel):
@ -465,7 +465,7 @@ class BankProfileResponse(BaseModel):
"example": {
"bank_id": "user123",
"name": "Alice",
"personality": {
"disposition": {
"openness": 0.8,
"conscientiousness": 0.6,
"extraversion": 0.5,
@ -479,13 +479,13 @@ class BankProfileResponse(BaseModel):
bank_id: str
name: str
personality: PersonalityTraits
disposition: DispositionTraits
background: str
class UpdatePersonalityRequest(BaseModel):
"""Request model for updating personality traits."""
personality: PersonalityTraits
class UpdateDispositionRequest(BaseModel):
"""Request model for updating disposition traits."""
disposition: DispositionTraits
class AddBackgroundRequest(BaseModel):
@ -493,14 +493,14 @@ class AddBackgroundRequest(BaseModel):
model_config = ConfigDict(json_schema_extra={
"example": {
"content": "I was born in Texas",
"update_personality": True
"update_disposition": True
}
})
content: str = Field(description="New background information to add or merge")
update_personality: bool = Field(
update_disposition: bool = Field(
default=True,
description="If true, infer Big Five personality traits from the merged background (default: true)"
description="If true, infer Big Five disposition traits from the merged background (default: true)"
)
@ -509,7 +509,7 @@ class BackgroundResponse(BaseModel):
model_config = ConfigDict(json_schema_extra={
"example": {
"background": "I was born in Texas. I am a software engineer with 10 years of experience.",
"personality": {
"disposition": {
"openness": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
@ -521,14 +521,14 @@ class BackgroundResponse(BaseModel):
})
background: str
personality: Optional[PersonalityTraits] = None
disposition: Optional[DispositionTraits] = None
class BankListItem(BaseModel):
"""Bank list item with profile summary."""
bank_id: str
name: str
personality: PersonalityTraits
disposition: DispositionTraits
background: str
created_at: Optional[str] = None
updated_at: Optional[str] = None
@ -542,7 +542,7 @@ class BankListResponse(BaseModel):
{
"bank_id": "user123",
"name": "Alice",
"personality": {
"disposition": {
"openness": 0.5,
"conscientiousness": 0.5,
"extraversion": 0.5,
@ -566,7 +566,7 @@ class CreateBankRequest(BaseModel):
model_config = ConfigDict(json_schema_extra={
"example": {
"name": "Alice",
"personality": {
"disposition": {
"openness": 0.8,
"conscientiousness": 0.6,
"extraversion": 0.5,
@ -579,7 +579,7 @@ class CreateBankRequest(BaseModel):
})
name: Optional[str] = None
personality: Optional[PersonalityTraits] = None
disposition: Optional[DispositionTraits] = None
background: Optional[str] = None
@ -833,7 +833,7 @@ def _register_routes(app: FastAPI):
"/v1/default/banks/{bank_id}/graph",
response_model=GraphDataResponse,
summary="Get memory graph data",
description="Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.",
description="Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.",
operation_id="get_graph"
)
async def api_graph(bank_id: str,
@ -871,7 +871,7 @@ def _register_routes(app: FastAPI):
Args:
bank_id: Memory Bank ID (from path)
type: Filter by fact type (world, interactions, opinion)
type: Filter by fact type (world, experience, opinion)
q: Search query for full-text search (searches text and context)
limit: Maximum number of results (default: 100)
offset: Offset for pagination (default: 0)
@ -901,7 +901,7 @@ def _register_routes(app: FastAPI):
The type parameter is optional and must be one of:
- 'world': General knowledge about people, places, events, and things that happen
- 'interactions': Memories about interactions, conversations, actions taken, and tasks performed
- 'experience': Memories about experience, conversations, actions taken, and tasks performed
- 'opinion': The bank's formed beliefs, perspectives, and viewpoints
Set include_entities=true to get entity observations alongside recall results.
@ -914,10 +914,10 @@ def _register_routes(app: FastAPI):
try:
# Validate types
valid_fact_types = ["world", "interactions", "opinion"]
valid_fact_types = ["world", "experience", "opinion"]
# Default to world, interactions, opinion if not specified (exclude observation by default)
fact_types = request.types if request.types else ["world", "interactions", "opinion"]
# Default to world, experience, opinion if not specified (exclude observation by default)
fact_types = request.types if request.types else ["world", "experience", "opinion"]
for ft in fact_types:
if ft not in valid_fact_types:
raise HTTPException(
@ -1026,7 +1026,7 @@ def _register_routes(app: FastAPI):
Reflect and formulate an answer using bank identity, world facts, and opinions.
This endpoint:
1. Retrieves interactions (conversations and events)
1. Retrieves experience (conversations and events)
2. Retrieves world facts relevant to the query
3. Retrieves existing opinions (bank's perspectives)
4. Uses LLM to formulate a contextual answer
@ -1579,19 +1579,19 @@ This operation cannot be undone.
"/v1/default/banks/{bank_id}/profile",
response_model=BankProfileResponse,
summary="Get memory bank profile",
description="Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.",
description="Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.",
operation_id="get_bank_profile"
)
async def api_get_bank_profile(bank_id: str):
"""Get memory bank profile (personality + background)."""
"""Get memory bank profile (disposition + background)."""
try:
profile = await app.state.memory.get_bank_profile(bank_id)
# Convert PersonalityTraits object to dict for Pydantic
personality_dict = profile["personality"].model_dump() if hasattr(profile["personality"], 'model_dump') else dict(profile["personality"])
# Convert DispositionTraits object to dict for Pydantic
disposition_dict = profile["disposition"].model_dump() if hasattr(profile["disposition"], 'model_dump') else dict(profile["disposition"])
return BankProfileResponse(
bank_id=bank_id,
name=profile["name"],
personality=PersonalityTraits(**personality_dict),
disposition=DispositionTraits(**disposition_dict),
background=profile["background"]
)
except Exception as e:
@ -1604,28 +1604,28 @@ This operation cannot be undone.
@app.put(
"/v1/default/banks/{bank_id}/profile",
response_model=BankProfileResponse,
summary="Update memory bank personality",
description="Update bank's Big Five personality traits and bias strength",
operation_id="update_bank_personality"
summary="Update memory bank disposition",
description="Update bank's Big Five disposition traits and bias strength",
operation_id="update_bank_disposition"
)
async def api_update_bank_personality(bank_id: str,
request: UpdatePersonalityRequest
async def api_update_bank_disposition(bank_id: str,
request: UpdateDispositionRequest
):
"""Update bank personality traits."""
"""Update bank disposition traits."""
try:
# Update personality
await app.state.memory.update_bank_personality(
# Update disposition
await app.state.memory.update_bank_disposition(
bank_id,
request.personality.model_dump()
request.disposition.model_dump()
)
# Get updated profile
profile = await app.state.memory.get_bank_profile(bank_id)
personality_dict = profile["personality"].model_dump() if hasattr(profile["personality"], 'model_dump') else dict(profile["personality"])
disposition_dict = profile["disposition"].model_dump() if hasattr(profile["disposition"], 'model_dump') else dict(profile["disposition"])
return BankProfileResponse(
bank_id=bank_id,
name=profile["name"],
personality=PersonalityTraits(**personality_dict),
disposition=DispositionTraits(**disposition_dict),
background=profile["background"]
)
except Exception as e:
@ -1639,23 +1639,23 @@ This operation cannot be undone.
"/v1/default/banks/{bank_id}/background",
response_model=BackgroundResponse,
summary="Add/merge memory bank background",
description="Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.",
description="Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.",
operation_id="add_bank_background"
)
async def api_add_bank_background(bank_id: str,
request: AddBackgroundRequest
):
"""Add or merge bank background information. Optionally infer personality traits."""
"""Add or merge bank background information. Optionally infer disposition traits."""
try:
result = await app.state.memory.merge_bank_background(
bank_id,
request.content,
update_personality=request.update_personality
update_disposition=request.update_disposition
)
response = BackgroundResponse(background=result["background"])
if "personality" in result:
response.personality = PersonalityTraits(**result["personality"])
if "disposition" in result:
response.disposition = DispositionTraits(**result["disposition"])
return response
except Exception as e:
@ -1669,13 +1669,13 @@ This operation cannot be undone.
"/v1/default/banks/{bank_id}",
response_model=BankProfileResponse,
summary="Create or update memory bank",
description="Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.",
description="Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.",
operation_id="create_or_update_bank"
)
async def api_create_or_update_bank(bank_id: str,
request: CreateBankRequest
):
"""Create or update an agent with personality and background."""
"""Create or update an agent with disposition and background."""
try:
# Get existing profile or create with defaults
profile = await app.state.memory.get_bank_profile(bank_id)
@ -1696,13 +1696,13 @@ This operation cannot be undone.
)
profile["name"] = request.name
# Update personality if provided
if request.personality is not None:
await app.state.memory.update_bank_personality(
# Update disposition if provided
if request.disposition is not None:
await app.state.memory.update_bank_disposition(
bank_id,
request.personality.model_dump()
request.disposition.model_dump()
)
profile["personality"] = request.personality.model_dump()
profile["disposition"] = request.disposition.model_dump()
# Update background if provided (replace, not merge)
if request.background is not None:
@ -1722,11 +1722,11 @@ This operation cannot be undone.
# Get final profile
final_profile = await app.state.memory.get_bank_profile(bank_id)
personality_dict = final_profile["personality"].model_dump() if hasattr(final_profile["personality"], 'model_dump') else dict(final_profile["personality"])
disposition_dict = final_profile["disposition"].model_dump() if hasattr(final_profile["disposition"], 'model_dump') else dict(final_profile["disposition"])
return BankProfileResponse(
bank_id=bank_id,
name=final_profile["name"],
personality=PersonalityTraits(**personality_dict),
disposition=DispositionTraits(**disposition_dict),
background=final_profile["background"]
)
except Exception as e:
@ -1852,11 +1852,11 @@ This operation cannot be undone.
"/v1/default/banks/{bank_id}/memories",
response_model=DeleteResponse,
summary="Clear memory bank memories",
description="Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.",
description="Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.",
operation_id="clear_bank_memories"
)
async def api_clear_bank_memories(bank_id: str,
type: Optional[str] = Query(None, description="Optional fact type filter (world, interactions, opinion)")
type: Optional[str] = Query(None, description="Optional fact type filter (world, experience, opinion)")
):
"""Clear memories for a memory bank, optionally filtered by type."""
try:

View file

@ -90,7 +90,7 @@ def create_mcp_server(memory: MemoryEngine) -> FastMCP:
search_result = await memory.recall_async(
bank_id=bank_id,
query=query,
fact_type=["world", "interactions", "opinion"],
fact_type=["world", "experience", "opinion"],
budget=Budget.LOW
)

View file

@ -94,7 +94,7 @@ class MemoryEngine:
- Embedding generation for semantic search
- Entity, temporal, and semantic link creation
- Think operations for formulating answers with opinions
- bank profile and personality management
- bank profile and disposition management
"""
def __init__(
@ -676,7 +676,7 @@ class MemoryEngine:
context: Context about when/why this memory was formed
event_date: When the event occurred (defaults to now)
document_id: Optional document ID for tracking (always upserts if document already exists)
fact_type_override: Override fact type ('world', 'interactions', 'opinion')
fact_type_override: Override fact type ('world', 'experience', 'opinion')
confidence_score: Confidence score for opinions (0.0 to 1.0)
Returns:
@ -728,7 +728,7 @@ class MemoryEngine:
- "document_id" (optional): Document ID for this specific content item
document_id: **DEPRECATED** - Use "document_id" key in each content dict instead.
Applies the same document_id to ALL content items that don't specify their own.
fact_type_override: Override fact type for all facts ('world', 'interactions', 'opinion')
fact_type_override: Override fact type for all facts ('world', 'experience', 'opinion')
confidence_score: Confidence score for opinions (0.0 to 1.0)
Returns:
@ -896,7 +896,7 @@ class MemoryEngine:
Args:
bank_id: bank ID to recall for
query: Recall query
fact_type: Required filter for fact type ('world', 'interactions', or 'opinion')
fact_type: Required filter for fact type ('world', 'experience', or 'opinion')
budget: Budget level for graph traversal (low=100, mid=300, high=600 units)
max_tokens: Maximum tokens to return (counts only 'text' field, default 4096)
enable_trace: If True, returns detailed trace object
@ -936,7 +936,7 @@ class MemoryEngine:
Args:
bank_id: bank ID to recall for
query: Recall query
fact_type: List of fact types to recall (e.g., ['world', 'interactions'])
fact_type: List of fact types to recall (e.g., ['world', 'experience'])
budget: Budget level for graph traversal (low=100, mid=300, high=600 units)
max_tokens: Maximum tokens to return (counts only 'text' field, default 4096)
Results are returned until token budget is reached, stopping before
@ -1682,7 +1682,7 @@ class MemoryEngine:
Args:
bank_id: bank ID to delete
fact_type: Optional fact type filter (world, bank, opinion). If provided, only deletes memories of that type.
fact_type: Optional fact type filter (world, experience, opinion). If provided, only deletes memories of that type.
Returns:
Dictionary with counts of deleted items
@ -1738,7 +1738,7 @@ class MemoryEngine:
Args:
bank_id: Filter by bank ID
fact_type: Filter by fact type (world, bank, opinion)
fact_type: Filter by fact type (world, experience, opinion)
Returns:
Dict with nodes, edges, and table_rows
@ -1912,7 +1912,7 @@ class MemoryEngine:
Args:
bank_id: Filter by bank ID
fact_type: Filter by fact type (world, bank, opinion)
fact_type: Filter by fact type (world, experience, opinion)
search_query: Full-text search query (searches text and context fields)
limit: Maximum number of results to return
offset: Offset for pagination
@ -2485,55 +2485,55 @@ Guidelines:
async def get_bank_profile(self, bank_id: str) -> "bank_utils.BankProfile":
"""
Get bank profile (name, personality + background).
Get bank profile (name, disposition + background).
Auto-creates agent with default values if not exists.
Args:
bank_id: bank IDentifier
Returns:
BankProfile with name, typed PersonalityTraits, and background
BankProfile with name, typed DispositionTraits, and background
"""
pool = await self._get_pool()
return await bank_utils.get_bank_profile(pool, bank_id)
async def update_bank_personality(
async def update_bank_disposition(
self,
bank_id: str,
personality: Dict[str, float]
disposition: Dict[str, float]
) -> None:
"""
Update bank personality traits.
Update bank disposition traits.
Args:
bank_id: bank IDentifier
personality: Dict with Big Five traits + bias_strength (all 0-1)
disposition: Dict with Big Five traits + bias_strength (all 0-1)
"""
pool = await self._get_pool()
await bank_utils.update_bank_personality(pool, bank_id, personality)
await bank_utils.update_bank_disposition(pool, bank_id, disposition)
async def merge_bank_background(
self,
bank_id: str,
new_info: str,
update_personality: bool = True
update_disposition: bool = True
) -> dict:
"""
Merge new background information with existing background using LLM.
Normalizes to first person ("I") and resolves conflicts.
Optionally infers personality traits from the merged background.
Optionally infers disposition traits from the merged background.
Args:
bank_id: bank IDentifier
new_info: New background information to add/merge
update_personality: If True, infer Big Five traits from background (default: True)
update_disposition: If True, infer Big Five traits from background (default: True)
Returns:
Dict with 'background' (str) and optionally 'personality' (dict) keys
Dict with 'background' (str) and optionally 'disposition' (dict) keys
"""
pool = await self._get_pool()
return await bank_utils.merge_bank_background(
pool, self._llm_config, bank_id, new_info, update_personality
pool, self._llm_config, bank_id, new_info, update_disposition
)
async def list_banks(self) -> list:
@ -2541,7 +2541,7 @@ Guidelines:
List all agents in the system.
Returns:
List of dicts with bank_id, name, personality, background, created_at, updated_at
List of dicts with bank_id, name, disposition, background, created_at, updated_at
"""
pool = await self._get_pool()
return await bank_utils.list_banks(pool)
@ -2559,7 +2559,7 @@ Guidelines:
Reflect and formulate an answer using bank identity, world facts, and opinions.
This method:
1. Retrieves interactions (conversations and events)
1. Retrieves experience (conversations and events)
2. Retrieves world facts (general knowledge)
3. Retrieves existing opinions (bank's formed perspectives)
4. Uses LLM to formulate an answer
@ -2575,7 +2575,7 @@ Guidelines:
Returns:
ReflectResult containing:
- text: Plain text answer (no markdown)
- based_on: Dict with 'world', 'interactions', and 'opinion' fact lists (MemoryFact objects)
- based_on: Dict with 'world', 'experience', and 'opinion' fact lists (MemoryFact objects)
- new_opinions: List of newly formed opinions
"""
# Use cached LLM config
@ -2589,7 +2589,7 @@ Guidelines:
budget=budget,
max_tokens=4096,
enable_trace=False,
fact_type=['interactions', 'world', 'opinion'],
fact_type=['experience', 'world', 'opinion'],
include_entities=True
)
@ -2597,7 +2597,7 @@ Guidelines:
logger.info(f"[THINK] Search returned {len(all_results)} results")
# Split results by fact type for structured response
agent_results = [r for r in all_results if r.fact_type == 'interactions']
agent_results = [r for r in all_results if r.fact_type == 'experience']
world_results = [r for r in all_results if r.fact_type == 'world']
opinion_results = [r for r in all_results if r.fact_type == 'opinion']
@ -2610,10 +2610,10 @@ Guidelines:
logger.info(f"[THINK] Formatted facts - agent: {len(agent_facts_text)} chars, world: {len(world_facts_text)} chars, opinion: {len(opinion_facts_text)} chars")
# Get bank profile (name, personality + background)
# Get bank profile (name, disposition + background)
profile = await self.get_bank_profile(bank_id)
name = profile["name"]
personality = profile["personality"] # Typed as PersonalityTraits
disposition = profile["disposition"] # Typed as DispositionTraits
background = profile["background"]
# Build the prompt
@ -2623,14 +2623,14 @@ Guidelines:
opinion_facts_text=opinion_facts_text,
query=query,
name=name,
personality=personality,
disposition=disposition,
background=background,
context=context,
)
logger.info(f"[THINK] Full prompt length: {len(prompt)} chars")
system_message = think_utils.get_system_message(personality)
system_message = think_utils.get_system_message(disposition)
answer_text = await self._llm_config.call(
messages=[
@ -2657,7 +2657,7 @@ Guidelines:
text=answer_text,
based_on={
"world": world_results,
"interactions": agent_results,
"experience": agent_results,
"opinion": opinion_results
},
new_opinions=[] # Opinions are being extracted asynchronously
@ -2871,7 +2871,7 @@ Guidelines:
JOIN unit_entities ue ON mu.id = ue.unit_id
WHERE mu.bank_id = $1
AND ue.entity_id = $2
AND mu.fact_type IN ('world', 'interactions')
AND mu.fact_type IN ('world', 'experience')
ORDER BY mu.occurred_start DESC
LIMIT 50
""",

View file

@ -10,9 +10,9 @@ from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field, ConfigDict
class PersonalityTraits(BaseModel):
class DispositionTraits(BaseModel):
"""
Personality traits for a bank using the Big Five model.
Disposition traits for a bank using the Big Five model.
All traits are scored 0.0-1.0 where higher values indicate stronger presence of the trait.
"""
@ -21,7 +21,7 @@ class PersonalityTraits(BaseModel):
extraversion: float = Field(description="Extraversion and sociability (0.0-1.0)")
agreeableness: float = Field(description="Agreeableness and cooperation (0.0-1.0)")
neuroticism: float = Field(description="Emotional sensitivity and neuroticism (0.0-1.0)")
bias_strength: float = Field(description="How strongly personality influences thinking (0.0-1.0)")
bias_strength: float = Field(description="How strongly disposition influences thinking (0.0-1.0)")
model_config = ConfigDict(json_schema_extra={
"example": {
@ -61,7 +61,7 @@ class MemoryFact(BaseModel):
id: str = Field(description="Unique identifier for the memory fact")
text: str = Field(description="The actual text content of the memory")
fact_type: str = Field(description="Type of fact: 'world', 'interactions', 'opinion', or 'observation'")
fact_type: str = Field(description="Type of fact: 'world', 'experience', 'opinion', or 'observation'")
entities: Optional[List[str]] = Field(None, description="Entity names mentioned in this fact")
context: Optional[str] = Field(None, description="Additional context for the memory")
occurred_start: Optional[str] = Field(None, description="ISO format date when the event started occurring")
@ -142,7 +142,7 @@ class ReflectResult(BaseModel):
"occurred_end": "2024-01-15T10:30:00Z"
}
],
"interactions": [],
"experience": [],
"opinion": []
},
"new_opinions": [
@ -153,7 +153,7 @@ class ReflectResult(BaseModel):
text: str = Field(description="The formulated answer text")
based_on: Dict[str, List[MemoryFact]] = Field(
description="Facts used to formulate the answer, organized by type (world, interactions, opinion)"
description="Facts used to formulate the answer, organized by type (world, experience, opinion)"
)
new_opinions: List[str] = Field(
default_factory=list,

View file

@ -1,5 +1,5 @@
"""
bank profile utilities for personality and background management.
bank profile utilities for disposition and background management.
"""
import json
@ -8,11 +8,11 @@ import re
from typing import Dict, Optional, TypedDict
from pydantic import BaseModel, Field
from ..db_utils import acquire_with_retry
from ..response_models import PersonalityTraits
from ..response_models import DispositionTraits
logger = logging.getLogger(__name__)
DEFAULT_PERSONALITY = {
DEFAULT_DISPOSITION = {
"openness": 0.5,
"conscientiousness": 0.5,
"extraversion": 0.5,
@ -25,19 +25,19 @@ DEFAULT_PERSONALITY = {
class BankProfile(TypedDict):
"""Type for bank profile data."""
name: str
personality: PersonalityTraits
disposition: DispositionTraits
background: str
class BackgroundMergeResponse(BaseModel):
"""LLM response for background merge with personality inference."""
"""LLM response for background merge with disposition inference."""
background: str = Field(description="Merged background in first person perspective")
personality: PersonalityTraits = Field(description="Inferred Big Five personality traits")
disposition: DispositionTraits = Field(description="Inferred Big Five disposition traits")
async def get_bank_profile(pool, bank_id: str) -> BankProfile:
"""
Get bank profile (name, personality + background).
Get bank profile (name, disposition + background).
Auto-creates bank with default values if not exists.
Args:
@ -45,13 +45,13 @@ async def get_bank_profile(pool, bank_id: str) -> BankProfile:
bank_id: bank IDentifier
Returns:
BankProfile with name, typed PersonalityTraits, and background
BankProfile with name, typed DispositionTraits, and background
"""
async with acquire_with_retry(pool) as conn:
# Try to get existing bank
row = await conn.fetchrow(
"""
SELECT name, personality, background
SELECT name, disposition, background
FROM banks WHERE bank_id = $1
""",
bank_id
@ -59,48 +59,48 @@ async def get_bank_profile(pool, bank_id: str) -> BankProfile:
if row:
# asyncpg returns JSONB as a string, so parse it
personality_data = row["personality"]
if isinstance(personality_data, str):
personality_data = json.loads(personality_data)
disposition_data = row["disposition"]
if isinstance(disposition_data, str):
disposition_data = json.loads(disposition_data)
return BankProfile(
name=row["name"],
personality=PersonalityTraits(**personality_data),
disposition=DispositionTraits(**disposition_data),
background=row["background"]
)
# Bank doesn't exist, create with defaults
await conn.execute(
"""
INSERT INTO banks (bank_id, name, personality, background)
INSERT INTO banks (bank_id, name, disposition, background)
VALUES ($1, $2, $3::jsonb, $4)
ON CONFLICT (bank_id) DO NOTHING
""",
bank_id,
bank_id, # Default name is the bank_id
json.dumps(DEFAULT_PERSONALITY),
json.dumps(DEFAULT_DISPOSITION),
""
)
return BankProfile(
name=bank_id,
personality=PersonalityTraits(**DEFAULT_PERSONALITY),
disposition=DispositionTraits(**DEFAULT_DISPOSITION),
background=""
)
async def update_bank_personality(
async def update_bank_disposition(
pool,
bank_id: str,
personality: Dict[str, float]
disposition: Dict[str, float]
) -> None:
"""
Update bank personality traits.
Update bank disposition traits.
Args:
pool: Database connection pool
bank_id: bank IDentifier
personality: Dict with Big Five traits + bias_strength (all 0-1)
disposition: Dict with Big Five traits + bias_strength (all 0-1)
"""
# Ensure bank exists first
await get_bank_profile(pool, bank_id)
@ -109,12 +109,12 @@ async def update_bank_personality(
await conn.execute(
"""
UPDATE banks
SET personality = $2::jsonb,
SET disposition = $2::jsonb,
updated_at = NOW()
WHERE bank_id = $1
""",
bank_id,
json.dumps(personality)
json.dumps(disposition)
)
@ -123,53 +123,53 @@ async def merge_bank_background(
llm_config,
bank_id: str,
new_info: str,
update_personality: bool = True
update_disposition: bool = True
) -> dict:
"""
Merge new background information with existing background using LLM.
Normalizes to first person ("I") and resolves conflicts.
Optionally infers personality traits from the merged background.
Optionally infers disposition traits from the merged background.
Args:
pool: Database connection pool
llm_config: LLM configuration for background merging
bank_id: bank IDentifier
new_info: New background information to add/merge
update_personality: If True, infer Big Five traits from background (default: True)
update_disposition: If True, infer Big Five traits from background (default: True)
Returns:
Dict with 'background' (str) and optionally 'personality' (dict) keys
Dict with 'background' (str) and optionally 'disposition' (dict) keys
"""
# Get current profile
profile = await get_bank_profile(pool, bank_id)
current_background = profile["background"]
# Use LLM to merge backgrounds and optionally infer personality
# Use LLM to merge backgrounds and optionally infer disposition
result = await _llm_merge_background(
llm_config,
current_background,
new_info,
infer_personality=update_personality
infer_disposition=update_disposition
)
merged_background = result["background"]
inferred_personality = result.get("personality")
inferred_disposition = result.get("disposition")
# Update in database
async with acquire_with_retry(pool) as conn:
if inferred_personality:
# Update both background and personality
if inferred_disposition:
# Update both background and disposition
await conn.execute(
"""
UPDATE banks
SET background = $2,
personality = $3::jsonb,
disposition = $3::jsonb,
updated_at = NOW()
WHERE bank_id = $1
""",
bank_id,
merged_background,
json.dumps(inferred_personality)
json.dumps(inferred_disposition)
)
else:
# Update only background
@ -185,8 +185,8 @@ async def merge_bank_background(
)
response = {"background": merged_background}
if inferred_personality:
response["personality"] = inferred_personality
if inferred_disposition:
response["disposition"] = inferred_disposition
return response
@ -195,23 +195,23 @@ async def _llm_merge_background(
llm_config,
current: str,
new_info: str,
infer_personality: bool = False
infer_disposition: bool = False
) -> dict:
"""
Use LLM to intelligently merge background information.
Optionally infer Big Five personality traits from the merged background.
Optionally infer Big Five disposition traits from the merged background.
Args:
llm_config: LLM configuration to use
current: Current background text
new_info: New information to merge
infer_personality: If True, also infer personality traits
infer_disposition: If True, also infer disposition traits
Returns:
Dict with 'background' (str) and optionally 'personality' (dict) keys
Dict with 'background' (str) and optionally 'disposition' (dict) keys
"""
if infer_personality:
prompt = f"""You are helping maintain a memory bank's background/profile and infer their personality. You MUST respond with ONLY valid JSON.
if infer_disposition:
prompt = f"""You are helping maintain a memory bank's background/profile and infer their disposition. You MUST respond with ONLY valid JSON.
Current background: {current if current else "(empty)"}
@ -223,20 +223,20 @@ Instructions:
3. Keep additions that don't conflict
4. Output in FIRST PERSON ("I") perspective
5. Be concise - keep merged background under 500 characters
6. Infer Big Five personality traits from the merged background:
6. Infer Big Five disposition traits from the merged background:
- Openness: 0.0-1.0 (creativity, curiosity, openness to new ideas)
- Conscientiousness: 0.0-1.0 (organization, discipline, goal-directed)
- Extraversion: 0.0-1.0 (sociability, assertiveness, energy from others)
- Agreeableness: 0.0-1.0 (cooperation, empathy, consideration)
- Neuroticism: 0.0-1.0 (emotional sensitivity, anxiety, stress response)
- Bias Strength: 0.0-1.0 (how much personality influences opinions)
- Bias Strength: 0.0-1.0 (how much disposition influences opinions)
CRITICAL: You MUST respond with ONLY a valid JSON object. No markdown, no code blocks, no explanations. Just the JSON.
Format:
{{
"background": "the merged background text in first person",
"personality": {{
"disposition": {{
"openness": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
@ -274,8 +274,8 @@ Merged background:"""
# Prepare messages
messages = [{"role": "user", "content": prompt}]
if infer_personality:
# Use structured output with Pydantic model for personality inference
if infer_disposition:
# Use structured output with Pydantic model for disposition inference
try:
parsed = await llm_config.call(
messages=messages,
@ -289,13 +289,13 @@ Merged background:"""
# Convert Pydantic model to dict format
return {
"background": parsed.background,
"personality": parsed.personality.model_dump()
"disposition": parsed.disposition.model_dump()
}
except Exception as e:
logger.warning(f"Structured output failed, falling back to manual parsing: {e}")
# Fall through to manual parsing below
# Manual parsing fallback or non-personality merge
# Manual parsing fallback or non-disposition merge
content = await llm_config.call(
messages=messages,
scope="bank_background",
@ -305,7 +305,7 @@ Merged background:"""
logger.info(f"LLM response for background merge (first 500 chars): {content[:500]}")
if infer_personality:
if infer_disposition:
# Parse JSON response - try multiple extraction methods
result = None
@ -330,7 +330,7 @@ Merged background:"""
# Method 3: Find nested JSON structure
if result is None:
# Look for JSON object with nested structure
json_match = re.search(r'\{[^{}]*"background"[^{}]*"personality"[^{}]*\{[^{}]*\}[^{}]*\}', content, re.DOTALL)
json_match = re.search(r'\{[^{}]*"background"[^{}]*"disposition"[^{}]*\{[^{}]*\}[^{}]*\}', content, re.DOTALL)
if json_match:
try:
result = json.loads(json_match.group())
@ -341,23 +341,23 @@ Merged background:"""
# All parsing methods failed - use fallback
if result is None:
logger.warning(f"Failed to extract JSON from LLM response. Raw content: {content[:200]}")
# Fallback: use new_info as background with default personality
# Fallback: use new_info as background with default disposition
return {
"background": new_info if new_info else current if current else "",
"personality": DEFAULT_PERSONALITY.copy()
"disposition": DEFAULT_DISPOSITION.copy()
}
# Validate personality values
personality = result.get("personality", {})
# Validate disposition values
disposition = result.get("disposition", {})
for key in ["openness", "conscientiousness", "extraversion",
"agreeableness", "neuroticism", "bias_strength"]:
if key not in personality:
personality[key] = 0.5 # Default to neutral
if key not in disposition:
disposition[key] = 0.5 # Default to neutral
else:
# Clamp to [0, 1]
personality[key] = max(0.0, min(1.0, float(personality[key])))
disposition[key] = max(0.0, min(1.0, float(disposition[key])))
result["personality"] = personality
result["disposition"] = disposition
# Ensure background exists
if "background" not in result or not result["background"]:
@ -380,8 +380,8 @@ Merged background:"""
merged = new_info
result = {"background": merged}
if infer_personality:
result["personality"] = DEFAULT_PERSONALITY.copy()
if infer_disposition:
result["disposition"] = DEFAULT_DISPOSITION.copy()
return result
@ -393,12 +393,12 @@ async def list_banks(pool) -> list:
pool: Database connection pool
Returns:
List of dicts with bank_id, name, personality, background, created_at, updated_at
List of dicts with bank_id, name, disposition, background, created_at, updated_at
"""
async with acquire_with_retry(pool) as conn:
rows = await conn.fetch(
"""
SELECT bank_id, name, personality, background, created_at, updated_at
SELECT bank_id, name, disposition, background, created_at, updated_at
FROM banks
ORDER BY updated_at DESC
"""
@ -407,14 +407,14 @@ async def list_banks(pool) -> list:
result = []
for row in rows:
# asyncpg returns JSONB as a string, so parse it
personality_data = row["personality"]
if isinstance(personality_data, str):
personality_data = json.loads(personality_data)
disposition_data = row["disposition"]
if isinstance(disposition_data, str):
disposition_data = json.loads(disposition_data)
result.append({
"bank_id": row["bank_id"],
"name": row["name"],
"personality": personality_data,
"disposition": disposition_data,
"background": row["background"],
"created_at": row["created_at"].isoformat() if row["created_at"] else None,
"updated_at": row["updated_at"].isoformat() if row["updated_at"] else None,

View file

@ -50,7 +50,7 @@ class Fact(BaseModel):
"""
# Required fields
fact: str = Field(description="Combined fact text: what | when | where | who | why")
fact_type: Literal["world", "interactions", "opinion"] = Field(description="Perspective: world/interactions/opinion")
fact_type: Literal["world", "experience", "opinion"] = Field(description="Perspective: world/experience/opinion")
# Optional temporal fields
occurred_start: Optional[str] = None
@ -164,7 +164,7 @@ class ExtractedFact(BaseModel):
# Classification (CRITICAL - required)
# Note: LLM uses "assistant" but we convert to "bank" for storage
fact_type: Literal["world", "assistant"] = Field(
description="'world' = about the user/others (background, experiences). 'assistant' = interactions with the assistant."
description="'world' = about the user/others (background, experiences). 'assistant' = experience with the assistant."
)
# Entities - extracted from 'who' field
@ -581,20 +581,20 @@ Text:
continue
# Critical field: fact_type
# LLM uses "assistant" but we convert to "interactions" for storage
# LLM uses "assistant" but we convert to "experience" for storage
fact_type = llm_fact.get('fact_type')
# Convert "assistant" → "interactions" for storage
# Convert "assistant" → "experience" for storage
if fact_type == 'assistant':
fact_type = 'interactions'
fact_type = 'experience'
# Validate fact_type (after conversion)
if fact_type not in ['world', 'interactions', 'opinion']:
if fact_type not in ['world', 'experience', 'opinion']:
# Try to fix common mistakes - check if they swapped fact_type and fact_kind
fact_kind = llm_fact.get('fact_kind')
if fact_kind == 'assistant':
fact_type = 'interactions'
elif fact_kind in ['world', 'interactions', 'opinion']:
fact_type = 'experience'
elif fact_kind in ['world', 'experience', 'opinion']:
fact_type = fact_kind
else:
# Default to 'world' if we can't determine

View file

@ -112,7 +112,7 @@ async def ensure_bank_exists(conn, bank_id: str) -> None:
"""
await conn.execute(
"""
INSERT INTO banks (bank_id, personality, background)
INSERT INTO banks (bank_id, disposition, background)
VALUES ($1, $2::jsonb, $3)
ON CONFLICT (bank_id) DO UPDATE
SET updated_at = NOW()

View file

@ -107,7 +107,18 @@ def compute_temporal_query_bounds(
def _log(log_buffer, message, level='info'):
"""Helper to log to buffer if available, otherwise use logger."""
"""Helper to log to buffer if available, otherwise use logger.
Args:
log_buffer: Buffer to append messages to (for main output)
message: The log message
level: 'info', 'debug', 'warning', or 'error'. Debug messages are not added to buffer.
"""
if level == 'debug':
# Debug messages only go to logger, not to buffer
logger.debug(message)
return
if log_buffer is not None:
log_buffer.append(message)
else:
@ -165,7 +176,7 @@ async def extract_entities_batch_optimized(
all_entities.append(formatted_entities)
total_entities = sum(len(ents) for ents in all_entities)
_log(log_buffer, f" [6.1] Process LLM entities: {total_entities} entities from {len(sentences)} facts in {time.time() - substep_start:.3f}s")
_log(log_buffer, f" [6.1] Process LLM entities: {total_entities} entities from {len(sentences)} facts in {time.time() - substep_start:.3f}s", level='debug')
# Step 2: Resolve entities in BATCH (much faster!)
substep_start = time.time()
@ -187,7 +198,7 @@ async def extract_entities_batch_optimized(
'nearby_entities': entities,
})
entity_to_unit.append((unit_id, local_idx, fact_date))
_log(log_buffer, f" [6.2.1] Prepare entities: {len(all_entities_flat)} entities in {time.time() - substep_6_2_1_start:.3f}s")
_log(log_buffer, f" [6.2.1] Prepare entities: {len(all_entities_flat)} entities in {time.time() - substep_6_2_1_start:.3f}s", level='debug')
# Resolve ALL entities in one batch call
if all_entities_flat:
@ -202,47 +213,36 @@ async def extract_entities_batch_optimized(
entities_by_date[date_key] = []
entities_by_date[date_key].append((idx, all_entities_flat[idx]))
_log(log_buffer, f" [6.2.2] Grouped into {len(entities_by_date)} date buckets, resolving in parallel...")
_log(log_buffer, f" [6.2.2] Grouped into {len(entities_by_date)} date buckets, resolving sequentially...", level='debug')
# Resolve all date groups in PARALLEL using asyncio.gather
# Resolve all date groups SEQUENTIALLY using main transaction connection
# This prevents race conditions where parallel tasks create duplicate entities
resolved_entity_ids = [None] * len(all_entities_flat)
# Prepare all resolution tasks
async def resolve_date_bucket(date_idx, date_key, entities_group):
for date_idx, (date_key, entities_group) in enumerate(entities_by_date.items(), 1):
date_bucket_start = time.time()
indices = [idx for idx, _ in entities_group]
entities_data = [entity_data for _, entity_data in entities_group]
# Use the first fact's date for this bucket (all should be in same hour)
fact_date = entity_to_unit[indices[0]][2]
# Pass conn=None to let each parallel task acquire its own connection
# Use main transaction connection to ensure consistency
batch_resolved = await entity_resolver.resolve_entities_batch(
bank_id=bank_id,
entities_data=entities_data,
context=context,
unit_event_date=fact_date,
conn=None # Each task gets its own connection from pool
conn=conn # Use main transaction connection
)
if len(entities_by_date) <= 10: # Only log individual buckets if there aren't too many
_log(log_buffer, f" [6.2.2.{date_idx}] Resolved {len(entities_data)} entities in {time.time() - date_bucket_start:.3f}s")
_log(log_buffer, f" [6.2.2.{date_idx}] Resolved {len(entities_data)} entities in {time.time() - date_bucket_start:.3f}s", level='debug')
return indices, batch_resolved
# Execute all resolution tasks in parallel
import asyncio
tasks = [
resolve_date_bucket(date_idx, date_key, entities_group)
for date_idx, (date_key, entities_group) in enumerate(entities_by_date.items(), 1)
]
results = await asyncio.gather(*tasks)
# Map results back to resolved_entity_ids
for indices, batch_resolved in results:
# Map results back to resolved_entity_ids
for idx, entity_id in zip(indices, batch_resolved):
resolved_entity_ids[idx] = entity_id
_log(log_buffer, f" [6.2.2] Resolve entities: {len(all_entities_flat)} entities across {len(entities_by_date)} buckets in {time.time() - substep_6_2_2_start:.3f}s")
_log(log_buffer, f" [6.2.2] Resolve entities: {len(all_entities_flat)} entities across {len(entities_by_date)} buckets in {time.time() - substep_6_2_2_start:.3f}s", level='debug')
# [6.2.3] Create unit-entity links in BATCH
substep_6_2_3_start = time.time()
@ -259,12 +259,12 @@ async def extract_entities_batch_optimized(
# Batch insert all unit-entity links (MUCH faster!)
await entity_resolver.link_units_to_entities_batch(unit_entity_pairs, conn=conn)
_log(log_buffer, f" [6.2.3] Create unit-entity links (batched): {len(unit_entity_pairs)} links in {time.time() - substep_6_2_3_start:.3f}s")
_log(log_buffer, f" [6.2.3] Create unit-entity links (batched): {len(unit_entity_pairs)} links in {time.time() - substep_6_2_3_start:.3f}s", level='debug')
_log(log_buffer, f" [6.2] Entity resolution (batched): {len(all_entities_flat)} entities resolved in {time.time() - step_6_2_start:.3f}s")
_log(log_buffer, f" [6.2] Entity resolution (batched): {len(all_entities_flat)} entities resolved in {time.time() - step_6_2_start:.3f}s", level='debug')
else:
unit_to_entity_ids = {}
_log(log_buffer, f" [6.2] Entity resolution (batched): 0 entities in {time.time() - step_6_2_start:.3f}s")
_log(log_buffer, f" [6.2] Entity resolution (batched): 0 entities in {time.time() - step_6_2_start:.3f}s", level='debug')
# Step 3: Create entity links between units that share entities
substep_start = time.time()
@ -273,7 +273,7 @@ async def extract_entities_batch_optimized(
for entity_ids in unit_to_entity_ids.values():
all_entity_ids.update(entity_ids)
_log(log_buffer, f" [6.3] Creating entity links for {len(all_entity_ids)} unique entities...")
_log(log_buffer, f" [6.3] Creating entity links for {len(all_entity_ids)} unique entities...", level='debug')
# Find all units that reference these entities (ONE batched query)
entity_to_units = {}
@ -289,7 +289,7 @@ async def extract_entities_batch_optimized(
""",
entity_id_list
)
_log(log_buffer, f" [6.3.1] Query unit_entities: {len(rows)} rows in {time.time() - query_start:.3f}s")
_log(log_buffer, f" [6.3.1] Query unit_entities: {len(rows)} rows in {time.time() - query_start:.3f}s", level='debug')
# Group by entity_id
group_start = time.time()
@ -298,21 +298,38 @@ async def extract_entities_batch_optimized(
if entity_id not in entity_to_units:
entity_to_units[entity_id] = []
entity_to_units[entity_id].append(row['unit_id'])
_log(log_buffer, f" [6.3.2] Group by entity_id: {time.time() - group_start:.3f}s")
_log(log_buffer, f" [6.3.2] Group by entity_id: {time.time() - group_start:.3f}s", level='debug')
# Create bidirectional links between units that share entities
# OPTIMIZATION: Limit links per entity to avoid N² explosion
# Only link each new unit to the most recent MAX_LINKS_PER_ENTITY units
MAX_LINKS_PER_ENTITY = 50 # Limit to prevent explosion when entity appears in many facts
link_gen_start = time.time()
links = []
new_unit_set = set(unit_ids) # Units from this batch
for entity_id, units_with_entity in entity_to_units.items():
# For each pair of units with this entity, create bidirectional links
for i, unit_id_1 in enumerate(units_with_entity):
for unit_id_2 in units_with_entity[i+1:]:
# Bidirectional links
# Separate new units (from this batch) and existing units
new_units = [u for u in units_with_entity if str(u) in new_unit_set or u in new_unit_set]
existing_units = [u for u in units_with_entity if str(u) not in new_unit_set and u not in new_unit_set]
# Link new units to each other (within batch) - also limited
# For very common entities, limit within-batch links too
new_units_to_link = new_units[-MAX_LINKS_PER_ENTITY:] if len(new_units) > MAX_LINKS_PER_ENTITY else new_units
for i, unit_id_1 in enumerate(new_units_to_link):
for unit_id_2 in new_units_to_link[i+1:]:
links.append((unit_id_1, unit_id_2, 'entity', 1.0, entity_id))
links.append((unit_id_2, unit_id_1, 'entity', 1.0, entity_id))
_log(log_buffer, f" [6.3.3] Generate {len(links)} links: {time.time() - link_gen_start:.3f}s")
_log(log_buffer, f" [6.3] Entity link creation: {len(links)} links for {len(all_entity_ids)} unique entities in {time.time() - substep_start:.3f}s")
# Link new units to LIMITED existing units (most recent)
existing_to_link = existing_units[-MAX_LINKS_PER_ENTITY:] # Take most recent
for new_unit in new_units:
for existing_unit in existing_to_link:
links.append((new_unit, existing_unit, 'entity', 1.0, entity_id))
links.append((existing_unit, new_unit, 'entity', 1.0, entity_id))
_log(log_buffer, f" [6.3.3] Generate {len(links)} links: {time.time() - link_gen_start:.3f}s", level='debug')
_log(log_buffer, f" [6.3] Entity link creation: {len(links)} links for {len(all_entity_ids)} unique entities in {time.time() - substep_start:.3f}s", level='debug')
return links
@ -546,8 +563,12 @@ async def insert_entity_links_batch(conn, links: List[tuple], chunk_size: int =
return
import uuid as uuid_mod
import time as time_mod
total_start = time_mod.time()
# Create temp table for bulk loading
create_start = time_mod.time()
await conn.execute("""
CREATE TEMP TABLE IF NOT EXISTS _temp_entity_links (
from_unit_id uuid,
@ -557,11 +578,15 @@ async def insert_entity_links_batch(conn, links: List[tuple], chunk_size: int =
entity_id uuid
) ON COMMIT DROP
""")
logger.debug(f" [9.1] Create temp table: {time_mod.time() - create_start:.3f}s")
# Clear any existing data in temp table
truncate_start = time_mod.time()
await conn.execute("TRUNCATE _temp_entity_links")
logger.debug(f" [9.2] Truncate temp table: {time_mod.time() - truncate_start:.3f}s")
# Convert links to proper format for COPY
convert_start = time_mod.time()
records = []
for from_id, to_id, link_type, weight, entity_id in links:
records.append((
@ -571,21 +596,27 @@ async def insert_entity_links_batch(conn, links: List[tuple], chunk_size: int =
weight,
uuid_mod.UUID(str(entity_id)) if entity_id and not isinstance(entity_id, uuid_mod.UUID) else entity_id
))
logger.debug(f" [9.3] Convert {len(records)} records: {time_mod.time() - convert_start:.3f}s")
# Bulk load using COPY (fastest method)
copy_start = time_mod.time()
await conn.copy_records_to_table(
'_temp_entity_links',
records=records,
columns=['from_unit_id', 'to_unit_id', 'link_type', 'weight', 'entity_id']
)
logger.debug(f" [9.4] COPY {len(records)} records to temp table: {time_mod.time() - copy_start:.3f}s")
# Insert from temp table with ON CONFLICT (single query for all rows)
insert_start = time_mod.time()
await conn.execute("""
INSERT INTO memory_links (from_unit_id, to_unit_id, link_type, weight, entity_id)
SELECT from_unit_id, to_unit_id, link_type, weight, entity_id
FROM _temp_entity_links
ON CONFLICT (from_unit_id, to_unit_id, link_type, COALESCE(entity_id, '00000000-0000-0000-0000-000000000000'::uuid)) DO NOTHING
""")
logger.debug(f" [9.5] INSERT from temp table: {time_mod.time() - insert_start:.3f}s")
logger.debug(f" [9.TOTAL] Entity links batch insert: {time_mod.time() - total_start:.3f}s")
async def create_causal_links_batch(

View file

@ -75,7 +75,7 @@ class ExtractedFact:
This is the raw output from fact extraction before processing.
"""
fact_text: str
fact_type: str # "world", "interactions", "opinion", "observation"
fact_type: str # "world", "experience", "opinion", "observation"
entities: List[str] = field(default_factory=list)
occurred_start: Optional[datetime] = None
occurred_end: Optional[datetime] = None

View file

@ -9,7 +9,7 @@ from datetime import datetime, timezone
from typing import Dict, List, Any
from pydantic import BaseModel, Field
from ..response_models import ReflectResult, MemoryFact, PersonalityTraits
from ..response_models import ReflectResult, MemoryFact, DispositionTraits
logger = logging.getLogger(__name__)
@ -42,16 +42,16 @@ def describe_trait(name: str, value: float) -> str:
return f"very low {name}"
def build_personality_description(personality: PersonalityTraits) -> str:
"""Build a personality description string from personality traits."""
return f"""Your personality traits:
- {describe_trait('openness to new ideas', personality.openness)}
- {describe_trait('conscientiousness and organization', personality.conscientiousness)}
- {describe_trait('extraversion and sociability', personality.extraversion)}
- {describe_trait('agreeableness and cooperation', personality.agreeableness)}
- {describe_trait('emotional sensitivity', personality.neuroticism)}
def build_disposition_description(disposition: DispositionTraits) -> str:
"""Build a disposition description string from disposition traits."""
return f"""Your disposition traits:
- {describe_trait('openness to new ideas', disposition.openness)}
- {describe_trait('conscientiousness and organization', disposition.conscientiousness)}
- {describe_trait('extraversion and sociability', disposition.extraversion)}
- {describe_trait('agreeableness and cooperation', disposition.agreeableness)}
- {describe_trait('emotional sensitivity', disposition.neuroticism)}
Personality influence strength: {int(personality.bias_strength * 100)}% (how much your personality shapes your opinions)"""
Disposition influence strength: {int(disposition.bias_strength * 100)}% (how much your disposition shapes your opinions)"""
def format_facts_for_prompt(facts: List[MemoryFact]) -> str:
@ -93,12 +93,12 @@ def build_think_prompt(
opinion_facts_text: str,
query: str,
name: str,
personality: PersonalityTraits,
disposition: DispositionTraits,
background: str,
context: str = None,
) -> str:
"""Build the think prompt for the LLM."""
personality_desc = build_personality_description(personality)
disposition_desc = build_disposition_description(disposition)
name_section = f"""
@ -132,24 +132,24 @@ WHAT I KNOW ABOUT THE WORLD:
MY EXISTING OPINIONS & BELIEFS:
{opinion_facts_text}
{context_section}{name_section}{personality_desc}{background_section}
{context_section}{name_section}{disposition_desc}{background_section}
QUESTION: {query}
Based on everything I know, believe, and who I am (including my name, personality and background), here's what I genuinely think about this question. I'll draw on my experiences, knowledge, opinions, and personal traits to give you my honest perspective."""
Based on everything I know, believe, and who I am (including my name, disposition and background), here's what I genuinely think about this question. I'll draw on my experiences, knowledge, opinions, and personal traits to give you my honest perspective."""
def get_system_message(personality: PersonalityTraits) -> str:
def get_system_message(disposition: DispositionTraits) -> str:
"""Get the system message for the think LLM call."""
bias_strength = personality.bias_strength
bias_strength = disposition.bias_strength
if bias_strength >= 0.7:
personality_instruction = "Your personality strongly influences your thinking. Let your traits guide how you interpret facts and form opinions. Don't be afraid to be biased based on your personality."
disposition_instruction = "Your disposition strongly influences your thinking. Let your traits guide how you interpret facts and form opinions. Don't be afraid to be biased based on your disposition."
elif bias_strength >= 0.4:
personality_instruction = "Your personality moderately influences your thinking. Balance your personal traits with objective analysis."
disposition_instruction = "Your disposition moderately influences your thinking. Balance your personal traits with objective analysis."
else:
personality_instruction = "Your personality has minimal influence on your thinking. Focus primarily on facts while keeping your traits in mind."
disposition_instruction = "Your disposition has minimal influence on your thinking. Focus primarily on facts while keeping your traits in mind."
return f"You are a person with your own thoughts, experiences, opinions, and personality. When asked a question, respond naturally like a human would - share what you genuinely think based on what you know and have experienced. {personality_instruction} Be direct, express your views confidently, and use 'I think', 'I believe', 'in my view', etc. Respond in plain text without markdown formatting."
return f"You are a person with your own thoughts, experiences, opinions, and disposition. When asked a question, respond naturally like a human would - share what you genuinely think based on what you know and have experienced. {disposition_instruction} Be direct, express your views confidently, and use 'I think', 'I believe', 'in my view', etc. Respond in plain text without markdown formatting."
async def extract_opinions_from_text(

View file

@ -100,7 +100,7 @@ class RetrievalResult(BaseModel):
text: str = Field(description="Memory unit text content")
context: str = Field(default="", description="Memory unit context")
event_date: Optional[datetime] = Field(default=None, description="When the memory occurred")
fact_type: Optional[str] = Field(default=None, description="Fact type (world, bank, opinion)")
fact_type: Optional[str] = Field(default=None, description="Fact type (world, experience, opinion)")
score: float = Field(description="Score from this retrieval method")
score_name: str = Field(description="Name of the score (e.g., 'similarity', 'bm25_score', 'activation')")

View file

@ -104,7 +104,7 @@ class MemoryUnit(Base):
name="memory_units_document_fkey",
ondelete="CASCADE",
),
CheckConstraint("fact_type IN ('world', 'interactions', 'opinion', 'observation')"),
CheckConstraint("fact_type IN ('world', 'experience', 'opinion', 'observation')"),
CheckConstraint("confidence_score IS NULL OR (confidence_score >= 0.0 AND confidence_score <= 1.0)"),
CheckConstraint(
"(fact_type = 'opinion' AND confidence_score IS NOT NULL) OR "
@ -284,11 +284,11 @@ class MemoryLink(Base):
class Bank(Base):
"""Memory bank profiles with personality traits and background."""
"""Memory bank profiles with disposition traits and background."""
__tablename__ = "banks"
bank_id: Mapped[str] = mapped_column(Text, primary_key=True)
personality: Mapped[dict] = mapped_column(
disposition: Mapped[dict] = mapped_column(
JSONB,
nullable=False,
server_default=sql_text(

View file

@ -4,7 +4,7 @@ Tests for agent management API (profile, personality, background).
import pytest
import uuid
from hindsight_api import MemoryEngine
from hindsight_api.api import CreateBankRequest, PersonalityTraits
from hindsight_api.api import CreateBankRequest, DispositionTraits
from hindsight_api.engine.memory_engine import Budget
@ -147,7 +147,7 @@ class TestAgentEndpoint:
bank_id = unique_agent_id("test_put_create")
request = CreateBankRequest(
personality=PersonalityTraits(
personality=DispositionTraits(
openness=0.8,
conscientiousness=0.6,
extraversion=0.5,

View file

@ -98,18 +98,18 @@ impl ApiClient {
let request = types::CreateBankRequest {
name: Some(name.to_string()),
background: None,
personality: None,
disposition: None,
};
let response = self.client.create_or_update_bank(agent_id, &request).await?;
Ok(response.into_inner())
})
}
pub fn add_background(&self, agent_id: &str, content: &str, update_personality: bool, _verbose: bool) -> Result<types::BackgroundResponse> {
pub fn add_background(&self, agent_id: &str, content: &str, update_disposition: bool, _verbose: bool) -> Result<types::BackgroundResponse> {
self.runtime.block_on(async {
let request = types::AddBackgroundRequest {
content: content.to_string(),
update_personality,
update_disposition,
};
let response = self.client.add_bank_background(agent_id, &request).await?;
Ok(response.into_inner())

View file

@ -198,11 +198,11 @@ pub fn update_background(
client: &ApiClient,
bank_id: &str,
content: &str,
no_update_personality: bool,
no_update_disposition: bool,
verbose: bool,
output_format: OutputFormat
) -> Result<()> {
let current_profile = if !no_update_personality {
let current_profile = if !no_update_disposition {
client.get_profile(bank_id, verbose).ok()
} else {
None
@ -214,7 +214,7 @@ pub fn update_background(
None
};
let response = client.add_background(bank_id, content, !no_update_personality, verbose);
let response = client.add_background(bank_id, content, !no_update_disposition, verbose);
if let Some(sp) = spinner {
sp.finish_and_clear();
@ -226,11 +226,11 @@ pub fn update_background(
ui::print_success("Background updated successfully");
println!("\n{}", profile.background);
if !no_update_personality {
if !no_update_disposition {
if let (Some(old_p), Some(new_p)) =
(current_profile.as_ref().map(|p| p.personality.clone()), &profile.personality)
(current_profile.as_ref().map(|p| p.disposition.clone()), &profile.disposition)
{
println!("\nPersonality changes:");
println!("\nDisposition changes:");
println!(" Openness: {:.2}{:.2}", old_p.openness, new_p.openness);
println!(" Conscientiousness: {:.2}{:.2}", old_p.conscientiousness, new_p.conscientiousness);
println!(" Extraversion: {:.2}{:.2}", old_p.extraversion, new_p.extraversion);

View file

@ -100,7 +100,7 @@ enum BankCommands {
/// List all banks
List,
/// Get bank profile (personality + background)
/// Get bank profile (disposition + background)
Profile {
/// Bank ID
bank_id: String,
@ -129,9 +129,9 @@ enum BankCommands {
/// Background content
content: String,
/// Skip automatic personality inference
/// Skip automatic disposition inference
#[arg(long)]
no_update_personality: bool,
no_update_disposition: bool,
},
}
@ -145,8 +145,8 @@ enum MemoryCommands {
/// Search query
query: String,
/// Fact types to search (world, interactions, opinion)
#[arg(short = 't', long, value_delimiter = ',', default_values = &["world", "interactions", "opinion"])]
/// Fact types to search (world, experience, opinion)
#[arg(short = 't', long, value_delimiter = ',', default_values = &["world", "experience", "opinion"])]
fact_type: Vec<String>,
/// Thinking budget (low, mid, high)
@ -381,8 +381,8 @@ fn run() -> Result<()> {
BankCommands::Profile { bank_id } => commands::bank::profile(&client, &bank_id, verbose, output_format),
BankCommands::Stats { bank_id } => commands::bank::stats(&client, &bank_id, verbose, output_format),
BankCommands::Name { bank_id, name } => commands::bank::update_name(&client, &bank_id, &name, verbose, output_format),
BankCommands::Background { bank_id, content, no_update_personality } => {
commands::bank::update_background(&client, &bank_id, &content, no_update_personality, verbose, output_format)
BankCommands::Background { bank_id, content, no_update_disposition } => {
commands::bank::update_background(&client, &bank_id, &content, no_update_disposition, verbose, output_format)
}
},

View file

@ -205,16 +205,16 @@ pub fn print_profile(profile: &BankProfileResponse) {
println!();
}
// Print personality traits
println!("{}", "─── Personality Traits ───".bright_yellow());
// Print disposition traits
println!("{}", "─── Disposition Traits ───".bright_yellow());
println!();
let traits = [
("Openness", profile.personality.openness, "🔓", "green"),
("Conscientiousness", profile.personality.conscientiousness, "📋", "yellow"),
("Extraversion", profile.personality.extraversion, "🗣️", "cyan"),
("Agreeableness", profile.personality.agreeableness, "🤝", "magenta"),
("Neuroticism", profile.personality.neuroticism, "😰", "yellow"),
("Openness", profile.disposition.openness, "🔓", "green"),
("Conscientiousness", profile.disposition.conscientiousness, "📋", "yellow"),
("Extraversion", profile.disposition.extraversion, "🗣️", "cyan"),
("Agreeableness", profile.disposition.agreeableness, "🤝", "magenta"),
("Neuroticism", profile.disposition.neuroticism, "😰", "yellow"),
];
for (name, value, emoji, color) in &traits {
@ -241,17 +241,17 @@ pub fn print_profile(profile: &BankProfileResponse) {
println!();
println!("{}", "Bias Strength:".bright_yellow());
let bias = profile.personality.bias_strength;
let bias = profile.disposition.bias_strength;
let bar_length = 40;
let filled = (bias * bar_length as f64) as usize;
let empty = bar_length - filled;
let bar = format!("{}{}", "".repeat(filled), "".repeat(empty));
println!(" 💪 {:<20} [{}] {:.0}%",
"Personality Influence",
"Disposition Influence",
bar.bright_green(),
bias * 100.0
);
println!(" {}", "(how much personality shapes opinions)".bright_black());
println!(" {}", "(how much disposition shapes opinions)".bright_black());
println!();
}

View file

@ -17,6 +17,7 @@ hindsight_client_api/docs/ChunkResponse.md
hindsight_client_api/docs/CreateBankRequest.md
hindsight_client_api/docs/DefaultApi.md
hindsight_client_api/docs/DeleteResponse.md
hindsight_client_api/docs/DispositionTraits.md
hindsight_client_api/docs/DocumentResponse.md
hindsight_client_api/docs/EntityDetailResponse.md
hindsight_client_api/docs/EntityIncludeOptions.md
@ -32,7 +33,6 @@ hindsight_client_api/docs/ListMemoryUnitsResponse.md
hindsight_client_api/docs/MemoryItem.md
hindsight_client_api/docs/MetadataFilter.md
hindsight_client_api/docs/MonitoringApi.md
hindsight_client_api/docs/PersonalityTraits.md
hindsight_client_api/docs/RecallRequest.md
hindsight_client_api/docs/RecallResponse.md
hindsight_client_api/docs/RecallResult.md
@ -42,7 +42,7 @@ hindsight_client_api/docs/ReflectRequest.md
hindsight_client_api/docs/ReflectResponse.md
hindsight_client_api/docs/RetainRequest.md
hindsight_client_api/docs/RetainResponse.md
hindsight_client_api/docs/UpdatePersonalityRequest.md
hindsight_client_api/docs/UpdateDispositionRequest.md
hindsight_client_api/docs/ValidationError.md
hindsight_client_api/docs/ValidationErrorLocInner.md
hindsight_client_api/exceptions.py
@ -58,6 +58,7 @@ hindsight_client_api/models/chunk_include_options.py
hindsight_client_api/models/chunk_response.py
hindsight_client_api/models/create_bank_request.py
hindsight_client_api/models/delete_response.py
hindsight_client_api/models/disposition_traits.py
hindsight_client_api/models/document_response.py
hindsight_client_api/models/entity_detail_response.py
hindsight_client_api/models/entity_include_options.py
@ -72,7 +73,6 @@ hindsight_client_api/models/list_documents_response.py
hindsight_client_api/models/list_memory_units_response.py
hindsight_client_api/models/memory_item.py
hindsight_client_api/models/metadata_filter.py
hindsight_client_api/models/personality_traits.py
hindsight_client_api/models/recall_request.py
hindsight_client_api/models/recall_response.py
hindsight_client_api/models/recall_result.py
@ -82,7 +82,7 @@ hindsight_client_api/models/reflect_request.py
hindsight_client_api/models/reflect_response.py
hindsight_client_api/models/retain_request.py
hindsight_client_api/models/retain_response.py
hindsight_client_api/models/update_personality_request.py
hindsight_client_api/models/update_disposition_request.py
hindsight_client_api/models/validation_error.py
hindsight_client_api/models/validation_error_loc_inner.py
hindsight_client_api/rest.py
@ -99,6 +99,7 @@ hindsight_client_api/test/test_chunk_response.py
hindsight_client_api/test/test_create_bank_request.py
hindsight_client_api/test/test_default_api.py
hindsight_client_api/test/test_delete_response.py
hindsight_client_api/test/test_disposition_traits.py
hindsight_client_api/test/test_document_response.py
hindsight_client_api/test/test_entity_detail_response.py
hindsight_client_api/test/test_entity_include_options.py
@ -114,7 +115,6 @@ hindsight_client_api/test/test_list_memory_units_response.py
hindsight_client_api/test/test_memory_item.py
hindsight_client_api/test/test_metadata_filter.py
hindsight_client_api/test/test_monitoring_api.py
hindsight_client_api/test/test_personality_traits.py
hindsight_client_api/test/test_recall_request.py
hindsight_client_api/test/test_recall_response.py
hindsight_client_api/test/test_recall_result.py
@ -124,7 +124,7 @@ hindsight_client_api/test/test_reflect_request.py
hindsight_client_api/test/test_reflect_response.py
hindsight_client_api/test/test_retain_request.py
hindsight_client_api/test/test_retain_response.py
hindsight_client_api/test/test_update_personality_request.py
hindsight_client_api/test/test_update_disposition_request.py
hindsight_client_api/test/test_validation_error.py
hindsight_client_api/test/test_validation_error_loc_inner.py
hindsight_client_api_README.md

View file

@ -164,7 +164,7 @@ class Hindsight:
Args:
bank_id: The memory bank ID
query: Search query
types: Optional list of fact types to filter (world, interactions, opinion, observation)
types: Optional list of fact types to filter (world, experience, opinion, observation)
max_tokens: Maximum tokens in results (default: 4096)
budget: Budget level for recall - "low", "mid", or "high" (default: "mid")
@ -229,7 +229,7 @@ class Hindsight:
Args:
bank_id: The memory bank ID
query: Search query
types: Optional list of fact types to filter (world, interactions, opinion, observation)
types: Optional list of fact types to filter (world, experience, opinion, observation)
budget: Budget level - "low", "mid", or "high"
max_tokens: Maximum tokens in results
trace: Enable trace output
@ -379,7 +379,7 @@ class Hindsight:
Args:
bank_id: The memory bank ID
query: Search query
types: Optional list of fact types to filter (world, interactions, opinion, observation)
types: Optional list of fact types to filter (world, experience, opinion, observation)
max_tokens: Maximum tokens in results (default: 4096)
budget: Budget level for recall - "low", "mid", or "high" (default: "mid")

View file

@ -40,6 +40,7 @@ __all__ = [
"ChunkResponse",
"CreateBankRequest",
"DeleteResponse",
"DispositionTraits",
"DocumentResponse",
"EntityDetailResponse",
"EntityIncludeOptions",
@ -54,7 +55,6 @@ __all__ = [
"ListMemoryUnitsResponse",
"MemoryItem",
"MetadataFilter",
"PersonalityTraits",
"RecallRequest",
"RecallResponse",
"RecallResult",
@ -64,7 +64,7 @@ __all__ = [
"ReflectResponse",
"RetainRequest",
"RetainResponse",
"UpdatePersonalityRequest",
"UpdateDispositionRequest",
"ValidationError",
"ValidationErrorLocInner",
]
@ -96,6 +96,7 @@ from hindsight_client_api.models.chunk_include_options import ChunkIncludeOption
from hindsight_client_api.models.chunk_response import ChunkResponse as ChunkResponse
from hindsight_client_api.models.create_bank_request import CreateBankRequest as CreateBankRequest
from hindsight_client_api.models.delete_response import DeleteResponse as DeleteResponse
from hindsight_client_api.models.disposition_traits import DispositionTraits as DispositionTraits
from hindsight_client_api.models.document_response import DocumentResponse as DocumentResponse
from hindsight_client_api.models.entity_detail_response import EntityDetailResponse as EntityDetailResponse
from hindsight_client_api.models.entity_include_options import EntityIncludeOptions as EntityIncludeOptions
@ -110,7 +111,6 @@ from hindsight_client_api.models.list_documents_response import ListDocumentsRes
from hindsight_client_api.models.list_memory_units_response import ListMemoryUnitsResponse as ListMemoryUnitsResponse
from hindsight_client_api.models.memory_item import MemoryItem as MemoryItem
from hindsight_client_api.models.metadata_filter import MetadataFilter as MetadataFilter
from hindsight_client_api.models.personality_traits import PersonalityTraits as PersonalityTraits
from hindsight_client_api.models.recall_request import RecallRequest as RecallRequest
from hindsight_client_api.models.recall_response import RecallResponse as RecallResponse
from hindsight_client_api.models.recall_result import RecallResult as RecallResult
@ -120,7 +120,7 @@ from hindsight_client_api.models.reflect_request import ReflectRequest as Reflec
from hindsight_client_api.models.reflect_response import ReflectResponse as ReflectResponse
from hindsight_client_api.models.retain_request import RetainRequest as RetainRequest
from hindsight_client_api.models.retain_response import RetainResponse as RetainResponse
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest as UpdatePersonalityRequest
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest as UpdateDispositionRequest
from hindsight_client_api.models.validation_error import ValidationError as ValidationError
from hindsight_client_api.models.validation_error_loc_inner import ValidationErrorLocInner as ValidationErrorLocInner

View file

@ -38,7 +38,7 @@ from hindsight_client_api.models.reflect_request import ReflectRequest
from hindsight_client_api.models.reflect_response import ReflectResponse
from hindsight_client_api.models.retain_request import RetainRequest
from hindsight_client_api.models.retain_response import RetainResponse
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest
from hindsight_client_api.api_client import ApiClient, RequestSerialized
from hindsight_client_api.api_response import ApiResponse
@ -78,7 +78,7 @@ class DefaultApi:
) -> BackgroundResponse:
"""Add/merge memory bank background
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
:param bank_id: (required)
:type bank_id: str
@ -150,7 +150,7 @@ class DefaultApi:
) -> ApiResponse[BackgroundResponse]:
"""Add/merge memory bank background
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
:param bank_id: (required)
:type bank_id: str
@ -222,7 +222,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Add/merge memory bank background
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
:param bank_id: (required)
:type bank_id: str
@ -631,7 +631,7 @@ class DefaultApi:
async def clear_bank_memories(
self,
bank_id: StrictStr,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, interactions, opinion)")] = None,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, experience, opinion)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -647,11 +647,11 @@ class DefaultApi:
) -> DeleteResponse:
"""Clear memory bank memories
Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
:param bank_id: (required)
:type bank_id: str
:param type: Optional fact type filter (world, interactions, opinion)
:param type: Optional fact type filter (world, experience, opinion)
:type type: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
@ -703,7 +703,7 @@ class DefaultApi:
async def clear_bank_memories_with_http_info(
self,
bank_id: StrictStr,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, interactions, opinion)")] = None,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, experience, opinion)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -719,11 +719,11 @@ class DefaultApi:
) -> ApiResponse[DeleteResponse]:
"""Clear memory bank memories
Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
:param bank_id: (required)
:type bank_id: str
:param type: Optional fact type filter (world, interactions, opinion)
:param type: Optional fact type filter (world, experience, opinion)
:type type: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
@ -775,7 +775,7 @@ class DefaultApi:
async def clear_bank_memories_without_preload_content(
self,
bank_id: StrictStr,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, interactions, opinion)")] = None,
type: Annotated[Optional[StrictStr], Field(description="Optional fact type filter (world, experience, opinion)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -791,11 +791,11 @@ class DefaultApi:
) -> RESTResponseType:
"""Clear memory bank memories
Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
:param bank_id: (required)
:type bank_id: str
:param type: Optional fact type filter (world, interactions, opinion)
:param type: Optional fact type filter (world, experience, opinion)
:type type: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
@ -927,7 +927,7 @@ class DefaultApi:
) -> BankProfileResponse:
"""Create or update memory bank
Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.
Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
:param bank_id: (required)
:type bank_id: str
@ -999,7 +999,7 @@ class DefaultApi:
) -> ApiResponse[BankProfileResponse]:
"""Create or update memory bank
Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.
Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
:param bank_id: (required)
:type bank_id: str
@ -1071,7 +1071,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Create or update memory bank
Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.
Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
:param bank_id: (required)
:type bank_id: str
@ -1758,7 +1758,7 @@ class DefaultApi:
) -> BankProfileResponse:
"""Get memory bank profile
Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.
Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
:param bank_id: (required)
:type bank_id: str
@ -1826,7 +1826,7 @@ class DefaultApi:
) -> ApiResponse[BankProfileResponse]:
"""Get memory bank profile
Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.
Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
:param bank_id: (required)
:type bank_id: str
@ -1894,7 +1894,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Get memory bank profile
Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.
Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
:param bank_id: (required)
:type bank_id: str
@ -2841,7 +2841,7 @@ class DefaultApi:
) -> GraphDataResponse:
"""Get memory graph data
Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.
Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
:param bank_id: (required)
:type bank_id: str
@ -2913,7 +2913,7 @@ class DefaultApi:
) -> ApiResponse[GraphDataResponse]:
"""Get memory graph data
Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.
Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
:param bank_id: (required)
:type bank_id: str
@ -2985,7 +2985,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Get memory graph data
Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.
Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
:param bank_id: (required)
:type bank_id: str
@ -4554,7 +4554,7 @@ class DefaultApi:
) -> RecallResponse:
"""Recall memory
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'interactions': Memories about interactions, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'experience': Memories about experience, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
:param bank_id: (required)
:type bank_id: str
@ -4626,7 +4626,7 @@ class DefaultApi:
) -> ApiResponse[RecallResponse]:
"""Recall memory
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'interactions': Memories about interactions, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'experience': Memories about experience, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
:param bank_id: (required)
:type bank_id: str
@ -4698,7 +4698,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Recall memory
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'interactions': Memories about interactions, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
Recall memory using semantic similarity and spreading activation. The type parameter is optional and must be one of: - 'world': General knowledge about people, places, events, and things that happen - 'experience': Memories about experience, conversations, actions taken, and tasks performed - 'opinion': The bank's formed beliefs, perspectives, and viewpoints Set include_entities=true to get entity observations alongside recall results.
:param bank_id: (required)
:type bank_id: str
@ -4845,7 +4845,7 @@ class DefaultApi:
) -> ReflectResponse:
"""Reflect and generate answer
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves interactions (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves experience (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
:param bank_id: (required)
:type bank_id: str
@ -4917,7 +4917,7 @@ class DefaultApi:
) -> ApiResponse[ReflectResponse]:
"""Reflect and generate answer
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves interactions (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves experience (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
:param bank_id: (required)
:type bank_id: str
@ -4989,7 +4989,7 @@ class DefaultApi:
) -> RESTResponseType:
"""Reflect and generate answer
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves interactions (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
Reflect and formulate an answer using bank identity, world facts, and opinions. This endpoint: 1. Retrieves experience (conversations and events) 2. Retrieves world facts relevant to the query 3. Retrieves existing opinions (bank's perspectives) 4. Uses LLM to formulate a contextual answer 5. Extracts and stores any new opinions formed 6. Returns plain text answer, the facts used, and new opinions
:param bank_id: (required)
:type bank_id: str
@ -5686,10 +5686,10 @@ class DefaultApi:
@validate_call
async def update_bank_personality(
async def update_bank_disposition(
self,
bank_id: StrictStr,
update_personality_request: UpdatePersonalityRequest,
update_disposition_request: UpdateDispositionRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -5703,14 +5703,14 @@ class DefaultApi:
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> BankProfileResponse:
"""Update memory bank personality
"""Update memory bank disposition
Update bank's Big Five personality traits and bias strength
Update bank's Big Five disposition traits and bias strength
:param bank_id: (required)
:type bank_id: str
:param update_personality_request: (required)
:type update_personality_request: UpdatePersonalityRequest
:param update_disposition_request: (required)
:type update_disposition_request: UpdateDispositionRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@ -5733,9 +5733,9 @@ class DefaultApi:
:return: Returns the result object.
""" # noqa: E501
_param = self._update_bank_personality_serialize(
_param = self._update_bank_disposition_serialize(
bank_id=bank_id,
update_personality_request=update_personality_request,
update_disposition_request=update_disposition_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@ -5758,10 +5758,10 @@ class DefaultApi:
@validate_call
async def update_bank_personality_with_http_info(
async def update_bank_disposition_with_http_info(
self,
bank_id: StrictStr,
update_personality_request: UpdatePersonalityRequest,
update_disposition_request: UpdateDispositionRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -5775,14 +5775,14 @@ class DefaultApi:
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> ApiResponse[BankProfileResponse]:
"""Update memory bank personality
"""Update memory bank disposition
Update bank's Big Five personality traits and bias strength
Update bank's Big Five disposition traits and bias strength
:param bank_id: (required)
:type bank_id: str
:param update_personality_request: (required)
:type update_personality_request: UpdatePersonalityRequest
:param update_disposition_request: (required)
:type update_disposition_request: UpdateDispositionRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@ -5805,9 +5805,9 @@ class DefaultApi:
:return: Returns the result object.
""" # noqa: E501
_param = self._update_bank_personality_serialize(
_param = self._update_bank_disposition_serialize(
bank_id=bank_id,
update_personality_request=update_personality_request,
update_disposition_request=update_disposition_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@ -5830,10 +5830,10 @@ class DefaultApi:
@validate_call
async def update_bank_personality_without_preload_content(
async def update_bank_disposition_without_preload_content(
self,
bank_id: StrictStr,
update_personality_request: UpdatePersonalityRequest,
update_disposition_request: UpdateDispositionRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@ -5847,14 +5847,14 @@ class DefaultApi:
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> RESTResponseType:
"""Update memory bank personality
"""Update memory bank disposition
Update bank's Big Five personality traits and bias strength
Update bank's Big Five disposition traits and bias strength
:param bank_id: (required)
:type bank_id: str
:param update_personality_request: (required)
:type update_personality_request: UpdatePersonalityRequest
:param update_disposition_request: (required)
:type update_disposition_request: UpdateDispositionRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@ -5877,9 +5877,9 @@ class DefaultApi:
:return: Returns the result object.
""" # noqa: E501
_param = self._update_bank_personality_serialize(
_param = self._update_bank_disposition_serialize(
bank_id=bank_id,
update_personality_request=update_personality_request,
update_disposition_request=update_disposition_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@ -5897,10 +5897,10 @@ class DefaultApi:
return response_data.response
def _update_bank_personality_serialize(
def _update_bank_disposition_serialize(
self,
bank_id,
update_personality_request,
update_disposition_request,
_request_auth,
_content_type,
_headers,
@ -5928,8 +5928,8 @@ class DefaultApi:
# process the header parameters
# process the form parameters
# process the body parameter
if update_personality_request is not None:
_body_params = update_personality_request
if update_disposition_request is not None:
_body_params = update_disposition_request
# set the HTTP header `Accept`

View file

@ -7,7 +7,7 @@ Request model for adding/merging background information.
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**content** | **str** | New background information to add or merge |
**update_personality** | **bool** | If true, infer Big Five personality traits from the merged background (default: true) | [optional] [default to True]
**update_disposition** | **bool** | If true, infer Big Five disposition traits from the merged background (default: true) | [optional] [default to True]
## Example

View file

@ -7,7 +7,7 @@ Response model for background update.
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**background** | **str** | |
**personality** | [**PersonalityTraits**](PersonalityTraits.md) | | [optional]
**disposition** | [**DispositionTraits**](DispositionTraits.md) | | [optional]
## Example

View file

@ -8,7 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**bank_id** | **str** | |
**name** | **str** | |
**personality** | [**PersonalityTraits**](PersonalityTraits.md) | |
**disposition** | [**DispositionTraits**](DispositionTraits.md) | |
**background** | **str** | |
**created_at** | **str** | | [optional]
**updated_at** | **str** | | [optional]

View file

@ -8,7 +8,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**bank_id** | **str** | |
**name** | **str** | |
**personality** | [**PersonalityTraits**](PersonalityTraits.md) | |
**disposition** | [**DispositionTraits**](DispositionTraits.md) | |
**background** | **str** | |
## Example

View file

@ -7,7 +7,7 @@ Request model for creating/updating a bank.
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | | [optional]
**personality** | [**PersonalityTraits**](PersonalityTraits.md) | | [optional]
**disposition** | [**DispositionTraits**](DispositionTraits.md) | | [optional]
**background** | **str** | | [optional]
## Example

View file

@ -24,7 +24,7 @@ Method | HTTP request | Description
[**reflect**](DefaultApi.md#reflect) | **POST** /v1/default/banks/{bank_id}/reflect | Reflect and generate answer
[**regenerate_entity_observations**](DefaultApi.md#regenerate_entity_observations) | **POST** /v1/default/banks/{bank_id}/entities/{entity_id}/regenerate | Regenerate entity observations
[**retain_memories**](DefaultApi.md#retain_memories) | **POST** /v1/default/banks/{bank_id}/memories | Retain memories
[**update_bank_personality**](DefaultApi.md#update_bank_personality) | **PUT** /v1/default/banks/{bank_id}/profile | Update memory bank personality
[**update_bank_disposition**](DefaultApi.md#update_bank_disposition) | **PUT** /v1/default/banks/{bank_id}/profile | Update memory bank disposition
# **add_bank_background**
@ -32,7 +32,7 @@ Method | HTTP request | Description
Add/merge memory bank background
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.
Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
### Example
@ -174,7 +174,7 @@ No authorization required
Clear memory bank memories
Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
### Example
@ -197,7 +197,7 @@ async with hindsight_client_api.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = hindsight_client_api.DefaultApi(api_client)
bank_id = 'bank_id_example' # str |
type = 'type_example' # str | Optional fact type filter (world, interactions, opinion) (optional)
type = 'type_example' # str | Optional fact type filter (world, experience, opinion) (optional)
try:
# Clear memory bank memories
@ -216,7 +216,7 @@ async with hindsight_client_api.ApiClient(configuration) as api_client:
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**bank_id** | **str**| |
**type** | **str**| Optional fact type filter (world, interactions, opinion) | [optional]
**type** | **str**| Optional fact type filter (world, experience, opinion) | [optional]
### Return type
@ -245,7 +245,7 @@ No authorization required
Create or update memory bank
Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.
Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
### Example
@ -462,7 +462,7 @@ No authorization required
Get memory bank profile
Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.
Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
### Example
@ -742,7 +742,7 @@ No authorization required
Get memory graph data
Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.
Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
### Example
@ -1172,7 +1172,7 @@ Recall memory using semantic similarity and spreading activation.
The type parameter is optional and must be one of:
- 'world': General knowledge about people, places, events, and things that happen
- 'interactions': Memories about interactions, conversations, actions taken, and tasks performed
- 'experience': Memories about experience, conversations, actions taken, and tasks performed
- 'opinion': The bank's formed beliefs, perspectives, and viewpoints
Set include_entities=true to get entity observations alongside recall results.
@ -1250,7 +1250,7 @@ Reflect and generate answer
Reflect and formulate an answer using bank identity, world facts, and opinions.
This endpoint:
1. Retrieves interactions (conversations and events)
1. Retrieves experience (conversations and events)
2. Retrieves world facts relevant to the query
3. Retrieves existing opinions (bank's perspectives)
4. Uses LLM to formulate a contextual answer
@ -1494,12 +1494,12 @@ No authorization required
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **update_bank_personality**
> BankProfileResponse update_bank_personality(bank_id, update_personality_request)
# **update_bank_disposition**
> BankProfileResponse update_bank_disposition(bank_id, update_disposition_request)
Update memory bank personality
Update memory bank disposition
Update bank's Big Five personality traits and bias strength
Update bank's Big Five disposition traits and bias strength
### Example
@ -1507,7 +1507,7 @@ Update bank's Big Five personality traits and bias strength
```python
import hindsight_client_api
from hindsight_client_api.models.bank_profile_response import BankProfileResponse
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest
from hindsight_client_api.rest import ApiException
from pprint import pprint
@ -1523,15 +1523,15 @@ async with hindsight_client_api.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = hindsight_client_api.DefaultApi(api_client)
bank_id = 'bank_id_example' # str |
update_personality_request = hindsight_client_api.UpdatePersonalityRequest() # UpdatePersonalityRequest |
update_disposition_request = hindsight_client_api.UpdateDispositionRequest() # UpdateDispositionRequest |
try:
# Update memory bank personality
api_response = await api_instance.update_bank_personality(bank_id, update_personality_request)
print("The response of DefaultApi->update_bank_personality:\n")
# Update memory bank disposition
api_response = await api_instance.update_bank_disposition(bank_id, update_disposition_request)
print("The response of DefaultApi->update_bank_disposition:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling DefaultApi->update_bank_personality: %s\n" % e)
print("Exception when calling DefaultApi->update_bank_disposition: %s\n" % e)
```
@ -1542,7 +1542,7 @@ async with hindsight_client_api.ApiClient(configuration) as api_client:
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**bank_id** | **str**| |
**update_personality_request** | [**UpdatePersonalityRequest**](UpdatePersonalityRequest.md)| |
**update_disposition_request** | [**UpdateDispositionRequest**](UpdateDispositionRequest.md)| |
### Return type

View file

@ -1,6 +1,6 @@
# PersonalityTraits
# DispositionTraits
Personality traits based on Big Five model.
Disposition traits based on Big Five model.
## Properties
@ -11,24 +11,24 @@ Name | Type | Description | Notes
**extraversion** | **float** | Extraversion (0-1) |
**agreeableness** | **float** | Agreeableness (0-1) |
**neuroticism** | **float** | Neuroticism (0-1) |
**bias_strength** | **float** | How strongly personality influences opinions (0-1) |
**bias_strength** | **float** | How strongly disposition influences opinions (0-1) |
## Example
```python
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
# TODO update the JSON string below
json = "{}"
# create an instance of PersonalityTraits from a JSON string
personality_traits_instance = PersonalityTraits.from_json(json)
# create an instance of DispositionTraits from a JSON string
disposition_traits_instance = DispositionTraits.from_json(json)
# print the JSON string representation of the object
print(PersonalityTraits.to_json())
print(DispositionTraits.to_json())
# convert the object into a dict
personality_traits_dict = personality_traits_instance.to_dict()
# create an instance of PersonalityTraits from a dict
personality_traits_from_dict = PersonalityTraits.from_dict(personality_traits_dict)
disposition_traits_dict = disposition_traits_instance.to_dict()
# create an instance of DispositionTraits from a dict
disposition_traits_from_dict = DispositionTraits.from_dict(disposition_traits_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View file

@ -0,0 +1,30 @@
# UpdateDispositionRequest
Request model for updating disposition traits.
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**disposition** | [**DispositionTraits**](DispositionTraits.md) | |
## Example
```python
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest
# TODO update the JSON string below
json = "{}"
# create an instance of UpdateDispositionRequest from a JSON string
update_disposition_request_instance = UpdateDispositionRequest.from_json(json)
# print the JSON string representation of the object
print(UpdateDispositionRequest.to_json())
# convert the object into a dict
update_disposition_request_dict = update_disposition_request_instance.to_dict()
# create an instance of UpdateDispositionRequest from a dict
update_disposition_request_from_dict = UpdateDispositionRequest.from_dict(update_disposition_request_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View file

@ -1,30 +0,0 @@
# UpdatePersonalityRequest
Request model for updating personality traits.
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**personality** | [**PersonalityTraits**](PersonalityTraits.md) | |
## Example
```python
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest
# TODO update the JSON string below
json = "{}"
# create an instance of UpdatePersonalityRequest from a JSON string
update_personality_request_instance = UpdatePersonalityRequest.from_json(json)
# print the JSON string representation of the object
print(UpdatePersonalityRequest.to_json())
# convert the object into a dict
update_personality_request_dict = update_personality_request_instance.to_dict()
# create an instance of UpdatePersonalityRequest from a dict
update_personality_request_from_dict = UpdatePersonalityRequest.from_dict(update_personality_request_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View file

@ -24,6 +24,7 @@ from hindsight_client_api.models.chunk_include_options import ChunkIncludeOption
from hindsight_client_api.models.chunk_response import ChunkResponse
from hindsight_client_api.models.create_bank_request import CreateBankRequest
from hindsight_client_api.models.delete_response import DeleteResponse
from hindsight_client_api.models.disposition_traits import DispositionTraits
from hindsight_client_api.models.document_response import DocumentResponse
from hindsight_client_api.models.entity_detail_response import EntityDetailResponse
from hindsight_client_api.models.entity_include_options import EntityIncludeOptions
@ -38,7 +39,6 @@ from hindsight_client_api.models.list_documents_response import ListDocumentsRes
from hindsight_client_api.models.list_memory_units_response import ListMemoryUnitsResponse
from hindsight_client_api.models.memory_item import MemoryItem
from hindsight_client_api.models.metadata_filter import MetadataFilter
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.recall_request import RecallRequest
from hindsight_client_api.models.recall_response import RecallResponse
from hindsight_client_api.models.recall_result import RecallResult
@ -48,7 +48,7 @@ from hindsight_client_api.models.reflect_request import ReflectRequest
from hindsight_client_api.models.reflect_response import ReflectResponse
from hindsight_client_api.models.retain_request import RetainRequest
from hindsight_client_api.models.retain_response import RetainResponse
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest
from hindsight_client_api.models.validation_error import ValidationError
from hindsight_client_api.models.validation_error_loc_inner import ValidationErrorLocInner

View file

@ -27,8 +27,8 @@ class AddBackgroundRequest(BaseModel):
Request model for adding/merging background information.
""" # noqa: E501
content: StrictStr = Field(description="New background information to add or merge")
update_personality: Optional[StrictBool] = Field(default=True, description="If true, infer Big Five personality traits from the merged background (default: true)")
__properties: ClassVar[List[str]] = ["content", "update_personality"]
update_disposition: Optional[StrictBool] = Field(default=True, description="If true, infer Big Five disposition traits from the merged background (default: true)")
__properties: ClassVar[List[str]] = ["content", "update_disposition"]
model_config = ConfigDict(
populate_by_name=True,
@ -82,7 +82,7 @@ class AddBackgroundRequest(BaseModel):
_obj = cls.model_validate({
"content": obj.get("content"),
"update_personality": obj.get("update_personality") if obj.get("update_personality") is not None else True
"update_disposition": obj.get("update_disposition") if obj.get("update_disposition") is not None else True
})
return _obj

View file

@ -19,7 +19,7 @@ import json
from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
from typing import Optional, Set
from typing_extensions import Self
@ -28,8 +28,8 @@ class BackgroundResponse(BaseModel):
Response model for background update.
""" # noqa: E501
background: StrictStr
personality: Optional[PersonalityTraits] = None
__properties: ClassVar[List[str]] = ["background", "personality"]
disposition: Optional[DispositionTraits] = None
__properties: ClassVar[List[str]] = ["background", "disposition"]
model_config = ConfigDict(
populate_by_name=True,
@ -70,13 +70,13 @@ class BackgroundResponse(BaseModel):
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of personality
if self.personality:
_dict['personality'] = self.personality.to_dict()
# set to None if personality (nullable) is None
# override the default output from pydantic by calling `to_dict()` of disposition
if self.disposition:
_dict['disposition'] = self.disposition.to_dict()
# set to None if disposition (nullable) is None
# and model_fields_set contains the field
if self.personality is None and "personality" in self.model_fields_set:
_dict['personality'] = None
if self.disposition is None and "disposition" in self.model_fields_set:
_dict['disposition'] = None
return _dict
@ -91,7 +91,7 @@ class BackgroundResponse(BaseModel):
_obj = cls.model_validate({
"background": obj.get("background"),
"personality": PersonalityTraits.from_dict(obj["personality"]) if obj.get("personality") is not None else None
"disposition": DispositionTraits.from_dict(obj["disposition"]) if obj.get("disposition") is not None else None
})
return _obj

View file

@ -19,7 +19,7 @@ import json
from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
from typing import Optional, Set
from typing_extensions import Self
@ -29,11 +29,11 @@ class BankListItem(BaseModel):
""" # noqa: E501
bank_id: StrictStr
name: StrictStr
personality: PersonalityTraits
disposition: DispositionTraits
background: StrictStr
created_at: Optional[StrictStr] = None
updated_at: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["bank_id", "name", "personality", "background", "created_at", "updated_at"]
__properties: ClassVar[List[str]] = ["bank_id", "name", "disposition", "background", "created_at", "updated_at"]
model_config = ConfigDict(
populate_by_name=True,
@ -74,9 +74,9 @@ class BankListItem(BaseModel):
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of personality
if self.personality:
_dict['personality'] = self.personality.to_dict()
# override the default output from pydantic by calling `to_dict()` of disposition
if self.disposition:
_dict['disposition'] = self.disposition.to_dict()
# set to None if created_at (nullable) is None
# and model_fields_set contains the field
if self.created_at is None and "created_at" in self.model_fields_set:
@ -101,7 +101,7 @@ class BankListItem(BaseModel):
_obj = cls.model_validate({
"bank_id": obj.get("bank_id"),
"name": obj.get("name"),
"personality": PersonalityTraits.from_dict(obj["personality"]) if obj.get("personality") is not None else None,
"disposition": DispositionTraits.from_dict(obj["disposition"]) if obj.get("disposition") is not None else None,
"background": obj.get("background"),
"created_at": obj.get("created_at"),
"updated_at": obj.get("updated_at")

View file

@ -19,7 +19,7 @@ import json
from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
from typing import Optional, Set
from typing_extensions import Self
@ -29,9 +29,9 @@ class BankProfileResponse(BaseModel):
""" # noqa: E501
bank_id: StrictStr
name: StrictStr
personality: PersonalityTraits
disposition: DispositionTraits
background: StrictStr
__properties: ClassVar[List[str]] = ["bank_id", "name", "personality", "background"]
__properties: ClassVar[List[str]] = ["bank_id", "name", "disposition", "background"]
model_config = ConfigDict(
populate_by_name=True,
@ -72,9 +72,9 @@ class BankProfileResponse(BaseModel):
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of personality
if self.personality:
_dict['personality'] = self.personality.to_dict()
# override the default output from pydantic by calling `to_dict()` of disposition
if self.disposition:
_dict['disposition'] = self.disposition.to_dict()
return _dict
@classmethod
@ -89,7 +89,7 @@ class BankProfileResponse(BaseModel):
_obj = cls.model_validate({
"bank_id": obj.get("bank_id"),
"name": obj.get("name"),
"personality": PersonalityTraits.from_dict(obj["personality"]) if obj.get("personality") is not None else None,
"disposition": DispositionTraits.from_dict(obj["disposition"]) if obj.get("disposition") is not None else None,
"background": obj.get("background")
})
return _obj

View file

@ -19,7 +19,7 @@ import json
from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
from typing import Optional, Set
from typing_extensions import Self
@ -28,9 +28,9 @@ class CreateBankRequest(BaseModel):
Request model for creating/updating a bank.
""" # noqa: E501
name: Optional[StrictStr] = None
personality: Optional[PersonalityTraits] = None
disposition: Optional[DispositionTraits] = None
background: Optional[StrictStr] = None
__properties: ClassVar[List[str]] = ["name", "personality", "background"]
__properties: ClassVar[List[str]] = ["name", "disposition", "background"]
model_config = ConfigDict(
populate_by_name=True,
@ -71,18 +71,18 @@ class CreateBankRequest(BaseModel):
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of personality
if self.personality:
_dict['personality'] = self.personality.to_dict()
# override the default output from pydantic by calling `to_dict()` of disposition
if self.disposition:
_dict['disposition'] = self.disposition.to_dict()
# set to None if name (nullable) is None
# and model_fields_set contains the field
if self.name is None and "name" in self.model_fields_set:
_dict['name'] = None
# set to None if personality (nullable) is None
# set to None if disposition (nullable) is None
# and model_fields_set contains the field
if self.personality is None and "personality" in self.model_fields_set:
_dict['personality'] = None
if self.disposition is None and "disposition" in self.model_fields_set:
_dict['disposition'] = None
# set to None if background (nullable) is None
# and model_fields_set contains the field
@ -102,7 +102,7 @@ class CreateBankRequest(BaseModel):
_obj = cls.model_validate({
"name": obj.get("name"),
"personality": PersonalityTraits.from_dict(obj["personality"]) if obj.get("personality") is not None else None,
"disposition": DispositionTraits.from_dict(obj["disposition"]) if obj.get("disposition") is not None else None,
"background": obj.get("background")
})
return _obj

View file

@ -23,16 +23,16 @@ from typing_extensions import Annotated
from typing import Optional, Set
from typing_extensions import Self
class PersonalityTraits(BaseModel):
class DispositionTraits(BaseModel):
"""
Personality traits based on Big Five model.
Disposition traits based on Big Five model.
""" # noqa: E501
openness: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="Openness to experience (0-1)")
conscientiousness: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="Conscientiousness (0-1)")
extraversion: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="Extraversion (0-1)")
agreeableness: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="Agreeableness (0-1)")
neuroticism: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="Neuroticism (0-1)")
bias_strength: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="How strongly personality influences opinions (0-1)")
bias_strength: Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="How strongly disposition influences opinions (0-1)")
__properties: ClassVar[List[str]] = ["openness", "conscientiousness", "extraversion", "agreeableness", "neuroticism", "bias_strength"]
model_config = ConfigDict(
@ -53,7 +53,7 @@ class PersonalityTraits(BaseModel):
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of PersonalityTraits from a JSON string"""
"""Create an instance of DispositionTraits from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
@ -78,7 +78,7 @@ class PersonalityTraits(BaseModel):
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of PersonalityTraits from a dict"""
"""Create an instance of DispositionTraits from a dict"""
if obj is None:
return None

View file

@ -19,16 +19,16 @@ import json
from pydantic import BaseModel, ConfigDict
from typing import Any, ClassVar, Dict, List
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
from typing import Optional, Set
from typing_extensions import Self
class UpdatePersonalityRequest(BaseModel):
class UpdateDispositionRequest(BaseModel):
"""
Request model for updating personality traits.
Request model for updating disposition traits.
""" # noqa: E501
personality: PersonalityTraits
__properties: ClassVar[List[str]] = ["personality"]
disposition: DispositionTraits
__properties: ClassVar[List[str]] = ["disposition"]
model_config = ConfigDict(
populate_by_name=True,
@ -48,7 +48,7 @@ class UpdatePersonalityRequest(BaseModel):
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of UpdatePersonalityRequest from a JSON string"""
"""Create an instance of UpdateDispositionRequest from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
@ -69,14 +69,14 @@ class UpdatePersonalityRequest(BaseModel):
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of personality
if self.personality:
_dict['personality'] = self.personality.to_dict()
# override the default output from pydantic by calling `to_dict()` of disposition
if self.disposition:
_dict['disposition'] = self.disposition.to_dict()
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of UpdatePersonalityRequest from a dict"""
"""Create an instance of UpdateDispositionRequest from a dict"""
if obj is None:
return None
@ -84,7 +84,7 @@ class UpdatePersonalityRequest(BaseModel):
return cls.model_validate(obj)
_obj = cls.model_validate({
"personality": PersonalityTraits.from_dict(obj["personality"]) if obj.get("personality") is not None else None
"disposition": DispositionTraits.from_dict(obj["disposition"]) if obj.get("disposition") is not None else None
})
return _obj

View file

@ -36,7 +36,7 @@ class TestAddBackgroundRequest(unittest.TestCase):
if include_optional:
return AddBackgroundRequest(
content = '',
update_personality = True
update_disposition = True
)
else:
return AddBackgroundRequest(

View file

@ -36,7 +36,7 @@ class TestBackgroundResponse(unittest.TestCase):
if include_optional:
return BackgroundResponse(
background = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8}
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8}
)
else:
return BackgroundResponse(

View file

@ -37,7 +37,7 @@ class TestBankListItem(unittest.TestCase):
return BankListItem(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = '',
created_at = '',
updated_at = ''
@ -46,7 +46,7 @@ class TestBankListItem(unittest.TestCase):
return BankListItem(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = '',
)
"""

View file

@ -39,7 +39,7 @@ class TestBankListResponse(unittest.TestCase):
hindsight_client_api.models.bank_list_item.BankListItem(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = '',
created_at = '',
updated_at = '', )
@ -51,7 +51,7 @@ class TestBankListResponse(unittest.TestCase):
hindsight_client_api.models.bank_list_item.BankListItem(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = '',
created_at = '',
updated_at = '', )

View file

@ -37,14 +37,14 @@ class TestBankProfileResponse(unittest.TestCase):
return BankProfileResponse(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = ''
)
else:
return BankProfileResponse(
bank_id = '',
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = '',
)
"""

View file

@ -36,7 +36,7 @@ class TestCreateBankRequest(unittest.TestCase):
if include_optional:
return CreateBankRequest(
name = '',
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
background = ''
)
else:

View file

@ -166,10 +166,10 @@ class TestDefaultApi(unittest.IsolatedAsyncioTestCase):
"""
pass
async def test_update_bank_personality(self) -> None:
"""Test case for update_bank_personality
async def test_update_bank_disposition(self) -> None:
"""Test case for update_bank_disposition
Update memory bank personality
Update memory bank disposition
"""
pass

View file

@ -14,10 +14,10 @@
import unittest
from hindsight_client_api.models.personality_traits import PersonalityTraits
from hindsight_client_api.models.disposition_traits import DispositionTraits
class TestPersonalityTraits(unittest.TestCase):
"""PersonalityTraits unit test stubs"""
class TestDispositionTraits(unittest.TestCase):
"""DispositionTraits unit test stubs"""
def setUp(self):
pass
@ -25,16 +25,16 @@ class TestPersonalityTraits(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional) -> PersonalityTraits:
"""Test PersonalityTraits
def make_instance(self, include_optional) -> DispositionTraits:
"""Test DispositionTraits
include_optional is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `PersonalityTraits`
# uncomment below to create an instance of `DispositionTraits`
"""
model = PersonalityTraits()
model = DispositionTraits()
if include_optional:
return PersonalityTraits(
return DispositionTraits(
openness = 0.0,
conscientiousness = 0.0,
extraversion = 0.0,
@ -43,7 +43,7 @@ class TestPersonalityTraits(unittest.TestCase):
bias_strength = 0.0
)
else:
return PersonalityTraits(
return DispositionTraits(
openness = 0.0,
conscientiousness = 0.0,
extraversion = 0.0,
@ -53,8 +53,8 @@ class TestPersonalityTraits(unittest.TestCase):
)
"""
def testPersonalityTraits(self):
"""Test PersonalityTraits"""
def testDispositionTraits(self):
"""Test DispositionTraits"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)

View file

@ -14,10 +14,10 @@
import unittest
from hindsight_client_api.models.update_personality_request import UpdatePersonalityRequest
from hindsight_client_api.models.update_disposition_request import UpdateDispositionRequest
class TestUpdatePersonalityRequest(unittest.TestCase):
"""UpdatePersonalityRequest unit test stubs"""
class TestUpdateDispositionRequest(unittest.TestCase):
"""UpdateDispositionRequest unit test stubs"""
def setUp(self):
pass
@ -25,26 +25,26 @@ class TestUpdatePersonalityRequest(unittest.TestCase):
def tearDown(self):
pass
def make_instance(self, include_optional) -> UpdatePersonalityRequest:
"""Test UpdatePersonalityRequest
def make_instance(self, include_optional) -> UpdateDispositionRequest:
"""Test UpdateDispositionRequest
include_optional is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `UpdatePersonalityRequest`
# uncomment below to create an instance of `UpdateDispositionRequest`
"""
model = UpdatePersonalityRequest()
model = UpdateDispositionRequest()
if include_optional:
return UpdatePersonalityRequest(
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8}
return UpdateDispositionRequest(
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8}
)
else:
return UpdatePersonalityRequest(
personality = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
return UpdateDispositionRequest(
disposition = {agreeableness=0.7, bias_strength=0.7, conscientiousness=0.6, extraversion=0.5, neuroticism=0.3, openness=0.8},
)
"""
def testUpdatePersonalityRequest(self):
"""Test UpdatePersonalityRequest"""
def testUpdateDispositionRequest(self):
"""Test UpdateDispositionRequest"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)

View file

@ -2,7 +2,7 @@
import type { Client, Options as Options2, TDataShape } from './client';
import { client } from './client.gen';
import type { AddBankBackgroundData, AddBankBackgroundErrors, AddBankBackgroundResponses, CancelOperationData, CancelOperationErrors, CancelOperationResponses, ClearBankMemoriesData, ClearBankMemoriesErrors, ClearBankMemoriesResponses, CreateOrUpdateBankData, CreateOrUpdateBankErrors, CreateOrUpdateBankResponses, DeleteDocumentData, DeleteDocumentErrors, DeleteDocumentResponses, GetAgentStatsData, GetAgentStatsErrors, GetAgentStatsResponses, GetBankProfileData, GetBankProfileErrors, GetBankProfileResponses, GetChunkData, GetChunkErrors, GetChunkResponses, GetDocumentData, GetDocumentErrors, GetDocumentResponses, GetEntityData, GetEntityErrors, GetEntityResponses, GetGraphData, GetGraphErrors, GetGraphResponses, HealthEndpointHealthGetData, HealthEndpointHealthGetResponses, ListBanksData, ListBanksResponses, ListDocumentsData, ListDocumentsErrors, ListDocumentsResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListMemoriesData, ListMemoriesErrors, ListMemoriesResponses, ListOperationsData, ListOperationsErrors, ListOperationsResponses, MetricsEndpointMetricsGetData, MetricsEndpointMetricsGetResponses, RecallMemoriesData, RecallMemoriesErrors, RecallMemoriesResponses, ReflectData, ReflectErrors, ReflectResponses, RegenerateEntityObservationsData, RegenerateEntityObservationsErrors, RegenerateEntityObservationsResponses, RetainMemoriesData, RetainMemoriesErrors, RetainMemoriesResponses, UpdateBankPersonalityData, UpdateBankPersonalityErrors, UpdateBankPersonalityResponses } from './types.gen';
import type { AddBankBackgroundData, AddBankBackgroundErrors, AddBankBackgroundResponses, CancelOperationData, CancelOperationErrors, CancelOperationResponses, ClearBankMemoriesData, ClearBankMemoriesErrors, ClearBankMemoriesResponses, CreateOrUpdateBankData, CreateOrUpdateBankErrors, CreateOrUpdateBankResponses, DeleteDocumentData, DeleteDocumentErrors, DeleteDocumentResponses, GetAgentStatsData, GetAgentStatsErrors, GetAgentStatsResponses, GetBankProfileData, GetBankProfileErrors, GetBankProfileResponses, GetChunkData, GetChunkErrors, GetChunkResponses, GetDocumentData, GetDocumentErrors, GetDocumentResponses, GetEntityData, GetEntityErrors, GetEntityResponses, GetGraphData, GetGraphErrors, GetGraphResponses, HealthEndpointHealthGetData, HealthEndpointHealthGetResponses, ListBanksData, ListBanksResponses, ListDocumentsData, ListDocumentsErrors, ListDocumentsResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListMemoriesData, ListMemoriesErrors, ListMemoriesResponses, ListOperationsData, ListOperationsErrors, ListOperationsResponses, MetricsEndpointMetricsGetData, MetricsEndpointMetricsGetResponses, RecallMemoriesData, RecallMemoriesErrors, RecallMemoriesResponses, ReflectData, ReflectErrors, ReflectResponses, RegenerateEntityObservationsData, RegenerateEntityObservationsErrors, RegenerateEntityObservationsResponses, RetainMemoriesData, RetainMemoriesErrors, RetainMemoriesResponses, UpdateBankDispositionData, UpdateBankDispositionErrors, UpdateBankDispositionResponses } from './types.gen';
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
/**
@ -35,7 +35,7 @@ export const metricsEndpointMetricsGet = <ThrowOnError extends boolean = false>(
/**
* Get memory graph data
*
* Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.
* Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
*/
export const getGraph = <ThrowOnError extends boolean = false>(options: Options<GetGraphData, ThrowOnError>) => (options.client ?? client).get<GetGraphResponses, GetGraphErrors, ThrowOnError>({ url: '/v1/default/banks/{bank_id}/graph', ...options });
@ -53,7 +53,7 @@ export const listMemories = <ThrowOnError extends boolean = false>(options: Opti
*
* The type parameter is optional and must be one of:
* - 'world': General knowledge about people, places, events, and things that happen
* - 'interactions': Memories about interactions, conversations, actions taken, and tasks performed
* - 'experience': Memories about experience, conversations, actions taken, and tasks performed
* - 'opinion': The bank's formed beliefs, perspectives, and viewpoints
*
* Set include_entities=true to get entity observations alongside recall results.
@ -73,7 +73,7 @@ export const recallMemories = <ThrowOnError extends boolean = false>(options: Op
* Reflect and formulate an answer using bank identity, world facts, and opinions.
*
* This endpoint:
* 1. Retrieves interactions (conversations and events)
* 1. Retrieves experience (conversations and events)
* 2. Retrieves world facts relevant to the query
* 3. Retrieves existing opinions (bank's perspectives)
* 4. Uses LLM to formulate a contextual answer
@ -176,16 +176,16 @@ export const cancelOperation = <ThrowOnError extends boolean = false>(options: O
/**
* Get memory bank profile
*
* Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.
* Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
*/
export const getBankProfile = <ThrowOnError extends boolean = false>(options: Options<GetBankProfileData, ThrowOnError>) => (options.client ?? client).get<GetBankProfileResponses, GetBankProfileErrors, ThrowOnError>({ url: '/v1/default/banks/{bank_id}/profile', ...options });
/**
* Update memory bank personality
* Update memory bank disposition
*
* Update bank's Big Five personality traits and bias strength
* Update bank's Big Five disposition traits and bias strength
*/
export const updateBankPersonality = <ThrowOnError extends boolean = false>(options: Options<UpdateBankPersonalityData, ThrowOnError>) => (options.client ?? client).put<UpdateBankPersonalityResponses, UpdateBankPersonalityErrors, ThrowOnError>({
export const updateBankDisposition = <ThrowOnError extends boolean = false>(options: Options<UpdateBankDispositionData, ThrowOnError>) => (options.client ?? client).put<UpdateBankDispositionResponses, UpdateBankDispositionErrors, ThrowOnError>({
url: '/v1/default/banks/{bank_id}/profile',
...options,
headers: {
@ -197,7 +197,7 @@ export const updateBankPersonality = <ThrowOnError extends boolean = false>(opti
/**
* Add/merge memory bank background
*
* Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.
* Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
*/
export const addBankBackground = <ThrowOnError extends boolean = false>(options: Options<AddBankBackgroundData, ThrowOnError>) => (options.client ?? client).post<AddBankBackgroundResponses, AddBankBackgroundErrors, ThrowOnError>({
url: '/v1/default/banks/{bank_id}/background',
@ -211,7 +211,7 @@ export const addBankBackground = <ThrowOnError extends boolean = false>(options:
/**
* Create or update memory bank
*
* Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.
* Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
*/
export const createOrUpdateBank = <ThrowOnError extends boolean = false>(options: Options<CreateOrUpdateBankData, ThrowOnError>) => (options.client ?? client).put<CreateOrUpdateBankResponses, CreateOrUpdateBankErrors, ThrowOnError>({
url: '/v1/default/banks/{bank_id}',
@ -225,7 +225,7 @@ export const createOrUpdateBank = <ThrowOnError extends boolean = false>(options
/**
* Clear memory bank memories
*
* Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
* Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.
*/
export const clearBankMemories = <ThrowOnError extends boolean = false>(options: Options<ClearBankMemoriesData, ThrowOnError>) => (options.client ?? client).delete<ClearBankMemoriesResponses, ClearBankMemoriesErrors, ThrowOnError>({ url: '/v1/default/banks/{bank_id}/memories', ...options });

View file

@ -17,11 +17,11 @@ export type AddBackgroundRequest = {
*/
content: string;
/**
* Update Personality
* Update Disposition
*
* If true, infer Big Five personality traits from the merged background (default: true)
* If true, infer Big Five disposition traits from the merged background (default: true)
*/
update_personality?: boolean;
update_disposition?: boolean;
};
/**
@ -34,7 +34,7 @@ export type BackgroundResponse = {
* Background
*/
background: string;
personality?: PersonalityTraits | null;
disposition?: DispositionTraits | null;
};
/**
@ -51,7 +51,7 @@ export type BankListItem = {
* Name
*/
name: string;
personality: PersonalityTraits;
disposition: DispositionTraits;
/**
* Background
*/
@ -92,7 +92,7 @@ export type BankProfileResponse = {
* Name
*/
name: string;
personality: PersonalityTraits;
disposition: DispositionTraits;
/**
* Background
*/
@ -188,7 +188,7 @@ export type CreateBankRequest = {
* Name
*/
name?: string | null;
personality?: PersonalityTraits | null;
disposition?: DispositionTraits | null;
/**
* Background
*/
@ -207,6 +207,50 @@ export type DeleteResponse = {
success: boolean;
};
/**
* DispositionTraits
*
* Disposition traits based on Big Five model.
*/
export type DispositionTraits = {
/**
* Openness
*
* Openness to experience (0-1)
*/
openness: number;
/**
* Conscientiousness
*
* Conscientiousness (0-1)
*/
conscientiousness: number;
/**
* Extraversion
*
* Extraversion (0-1)
*/
extraversion: number;
/**
* Agreeableness
*
* Agreeableness (0-1)
*/
agreeableness: number;
/**
* Neuroticism
*
* Neuroticism (0-1)
*/
neuroticism: number;
/**
* Bias Strength
*
* How strongly disposition influences opinions (0-1)
*/
bias_strength: number;
};
/**
* DocumentResponse
*
@ -552,50 +596,6 @@ export type MetadataFilter = {
match_unset?: boolean;
};
/**
* PersonalityTraits
*
* Personality traits based on Big Five model.
*/
export type PersonalityTraits = {
/**
* Openness
*
* Openness to experience (0-1)
*/
openness: number;
/**
* Conscientiousness
*
* Conscientiousness (0-1)
*/
conscientiousness: number;
/**
* Extraversion
*
* Extraversion (0-1)
*/
extraversion: number;
/**
* Agreeableness
*
* Agreeableness (0-1)
*/
agreeableness: number;
/**
* Neuroticism
*
* Neuroticism (0-1)
*/
neuroticism: number;
/**
* Bias Strength
*
* How strongly personality influences opinions (0-1)
*/
bias_strength: number;
};
/**
* RecallRequest
*
@ -859,12 +859,12 @@ export type RetainResponse = {
};
/**
* UpdatePersonalityRequest
* UpdateDispositionRequest
*
* Request model for updating personality traits.
* Request model for updating disposition traits.
*/
export type UpdatePersonalityRequest = {
personality: PersonalityTraits;
export type UpdateDispositionRequest = {
disposition: DispositionTraits;
};
/**
@ -1433,8 +1433,8 @@ export type GetBankProfileResponses = {
export type GetBankProfileResponse = GetBankProfileResponses[keyof GetBankProfileResponses];
export type UpdateBankPersonalityData = {
body: UpdatePersonalityRequest;
export type UpdateBankDispositionData = {
body: UpdateDispositionRequest;
path: {
/**
* Bank Id
@ -1445,23 +1445,23 @@ export type UpdateBankPersonalityData = {
url: '/v1/default/banks/{bank_id}/profile';
};
export type UpdateBankPersonalityErrors = {
export type UpdateBankDispositionErrors = {
/**
* Validation Error
*/
422: HttpValidationError;
};
export type UpdateBankPersonalityError = UpdateBankPersonalityErrors[keyof UpdateBankPersonalityErrors];
export type UpdateBankDispositionError = UpdateBankDispositionErrors[keyof UpdateBankDispositionErrors];
export type UpdateBankPersonalityResponses = {
export type UpdateBankDispositionResponses = {
/**
* Successful Response
*/
200: BankProfileResponse;
};
export type UpdateBankPersonalityResponse = UpdateBankPersonalityResponses[keyof UpdateBankPersonalityResponses];
export type UpdateBankDispositionResponse = UpdateBankDispositionResponses[keyof UpdateBankDispositionResponses];
export type AddBankBackgroundData = {
body: AddBackgroundRequest;
@ -1535,7 +1535,7 @@ export type ClearBankMemoriesData = {
/**
* Type
*
* Optional fact type filter (world, interactions, opinion)
* Optional fact type filter (world, experience, opinion)
*/
type?: string | null;
};

View file

@ -13,7 +13,7 @@ import { BankProfileView } from '@/components/bank-profile-view';
import { useBank } from '@/lib/bank-context';
type NavItem = 'recall' | 'reflect' | 'data' | 'documents' | 'entities' | 'profile';
type DataSubTab = 'world' | 'interactions' | 'opinion';
type DataSubTab = 'world' | 'experience' | 'opinion';
export default function BankPage() {
const params = useParams();
@ -54,7 +54,7 @@ export default function BankPage() {
<div>
<h1 className="text-3xl font-bold mb-2 text-foreground">Bank Profile</h1>
<p className="text-muted-foreground mb-6">
View and edit the memory bank profile, personality traits, and background information.
View and edit the memory bank profile, disposition traits, and background information.
</p>
<BankProfileView />
</div>
@ -106,15 +106,15 @@ export default function BankPage() {
)}
</button>
<button
onClick={() => handleDataSubTabChange('interactions')}
onClick={() => handleDataSubTabChange('experience')}
className={`px-6 py-3 font-semibold text-sm transition-all relative ${
subTab === 'interactions'
subTab === 'experience'
? 'text-primary'
: 'text-muted-foreground hover:text-foreground'
}`}
>
Interactions
{subTab === 'interactions' && (
Experience
{subTab === 'experience' && (
<div className="absolute bottom-0 left-0 right-0 h-0.5 bg-primary" />
)}
</button>
@ -136,7 +136,7 @@ export default function BankPage() {
<div>
{subTab === 'world' && <DataView key="world" factType="world" />}
{subTab === 'interactions' && <DataView key="interactions" factType="interactions" />}
{subTab === 'experience' && <DataView key="experience" factType="experience" />}
{subTab === 'opinion' && <DataView key="opinion" factType="opinion" />}
</div>
</div>

View file

@ -11,7 +11,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@
import { RefreshCw, Save, User, Brain, FileText, Clock, AlertCircle, CheckCircle, Database, Link2, FolderOpen, Activity } from 'lucide-react';
import { RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, Radar, ResponsiveContainer, Tooltip } from 'recharts';
interface PersonalityTraits {
interface DispositionTraits {
openness: number;
conscientiousness: number;
extraversion: number;
@ -23,7 +23,7 @@ interface PersonalityTraits {
interface BankProfile {
bank_id: string;
name: string;
personality: PersonalityTraits;
disposition: DispositionTraits;
background: string;
}
@ -34,7 +34,7 @@ interface BankStats {
total_documents: number;
nodes_by_fact_type: {
world?: number;
interactions?: number;
experience?: number;
opinion?: number;
};
links_by_link_type: {
@ -56,7 +56,7 @@ interface Operation {
error_message?: string;
}
const TRAIT_LABELS: Record<keyof PersonalityTraits, { label: string; shortLabel: string; description: string; lowLabel: string; highLabel: string }> = {
const TRAIT_LABELS: Record<keyof DispositionTraits, { label: string; shortLabel: string; description: string; lowLabel: string; highLabel: string }> = {
openness: {
label: 'Openness',
shortLabel: 'O',
@ -95,19 +95,19 @@ const TRAIT_LABELS: Record<keyof PersonalityTraits, { label: string; shortLabel:
bias_strength: {
label: 'Influence',
shortLabel: 'I',
description: 'How strongly personality traits influence opinions and responses',
description: 'How strongly disposition traits influence opinions and responses',
lowLabel: 'Neutral',
highLabel: 'Strong'
}
};
function PersonalityRadarChart({ personality, editMode, editPersonality, onEditChange }: {
personality: PersonalityTraits;
function DispositionRadarChart({ disposition, editMode, editDisposition, onEditChange }: {
disposition: DispositionTraits;
editMode: boolean;
editPersonality: PersonalityTraits;
onEditChange: (trait: keyof PersonalityTraits, value: number) => void;
editDisposition: DispositionTraits;
onEditChange: (trait: keyof DispositionTraits, value: number) => void;
}) {
const data = editMode ? editPersonality : personality;
const data = editMode ? editDisposition : disposition;
const chartData = [
{ trait: 'Openness', value: Math.round(data.openness * 100), fullMark: 100 },
@ -134,7 +134,7 @@ function PersonalityRadarChart({ personality, editMode, editPersonality, onEditC
tickCount={5}
/>
<Radar
name="Personality"
name="Disposition"
dataKey="value"
stroke="hsl(var(--primary))"
fill="hsl(var(--primary))"
@ -156,17 +156,17 @@ function PersonalityRadarChart({ personality, editMode, editPersonality, onEditC
{editMode && (
<div className="grid grid-cols-2 gap-3">
{(Object.keys(TRAIT_LABELS) as Array<keyof PersonalityTraits>).filter(t => t !== 'bias_strength').map((trait) => (
{(Object.keys(TRAIT_LABELS) as Array<keyof DispositionTraits>).filter(t => t !== 'bias_strength').map((trait) => (
<div key={trait} className="space-y-1">
<div className="flex justify-between items-center">
<label className="text-xs font-medium text-muted-foreground">{TRAIT_LABELS[trait].label}</label>
<span className="text-xs text-primary font-semibold">{Math.round(editPersonality[trait] * 100)}%</span>
<span className="text-xs text-primary font-semibold">{Math.round(editDisposition[trait] * 100)}%</span>
</div>
<input
type="range"
min="0"
max="100"
value={Math.round(editPersonality[trait] * 100)}
value={Math.round(editDisposition[trait] * 100)}
onChange={(e) => onEditChange(trait, parseInt(e.target.value) / 100)}
className="w-full h-1.5 bg-muted rounded-lg appearance-none cursor-pointer accent-primary"
/>
@ -179,7 +179,7 @@ function PersonalityRadarChart({ personality, editMode, editPersonality, onEditC
<div className="pt-3 border-t border-border">
<div className="flex justify-between items-center mb-2">
<div>
<label className="text-sm font-medium text-foreground">Personality Influence</label>
<label className="text-sm font-medium text-foreground">Disposition Influence</label>
<p className="text-xs text-muted-foreground">How strongly traits affect responses</p>
</div>
<span className="text-sm font-bold text-primary">{Math.round(data.bias_strength * 100)}%</span>
@ -189,7 +189,7 @@ function PersonalityRadarChart({ personality, editMode, editPersonality, onEditC
type="range"
min="0"
max="100"
value={Math.round(editPersonality.bias_strength * 100)}
value={Math.round(editDisposition.bias_strength * 100)}
onChange={(e) => onEditChange('bias_strength', parseInt(e.target.value) / 100)}
className="w-full h-2 bg-muted rounded-lg appearance-none cursor-pointer accent-primary"
/>
@ -211,7 +211,7 @@ export function BankProfileView() {
// Edit state
const [editName, setEditName] = useState('');
const [editBackground, setEditBackground] = useState('');
const [editPersonality, setEditPersonality] = useState<PersonalityTraits>({
const [editDisposition, setEditDisposition] = useState<DispositionTraits>({
openness: 0.5,
conscientiousness: 0.5,
extraversion: 0.5,
@ -237,7 +237,7 @@ export function BankProfileView() {
// Initialize edit state
setEditName(profileData.name);
setEditBackground(profileData.background);
setEditPersonality(profileData.personality);
setEditDisposition(profileData.disposition);
} catch (error) {
console.error('Error loading bank profile:', error);
alert('Error loading bank profile: ' + (error as Error).message);
@ -254,7 +254,7 @@ export function BankProfileView() {
await client.updateBankProfile(currentBank, {
name: editName,
background: editBackground,
personality: editPersonality
disposition: editDisposition
});
await loadData();
setEditMode(false);
@ -270,7 +270,7 @@ export function BankProfileView() {
if (profile) {
setEditName(profile.name);
setEditBackground(profile.background);
setEditPersonality(profile.personality);
setEditDisposition(profile.disposition);
}
setEditMode(false);
};
@ -417,8 +417,8 @@ export function BankProfileView() {
<p className="text-2xl font-bold text-blue-600 dark:text-blue-400 mt-1">{stats.nodes_by_fact_type?.world || 0}</p>
</div>
<div className="bg-purple-500/10 border border-purple-500/20 rounded-xl p-4 text-center">
<p className="text-xs text-purple-600 dark:text-purple-400 font-semibold uppercase tracking-wide">Interactions</p>
<p className="text-2xl font-bold text-purple-600 dark:text-purple-400 mt-1">{stats.nodes_by_fact_type?.interactions || 0}</p>
<p className="text-xs text-purple-600 dark:text-purple-400 font-semibold uppercase tracking-wide">Experience</p>
<p className="text-2xl font-bold text-purple-600 dark:text-purple-400 mt-1">{stats.nodes_by_fact_type?.experience || 0}</p>
</div>
<div className="bg-amber-500/10 border border-amber-500/20 rounded-xl p-4 text-center">
<p className="text-xs text-amber-600 dark:text-amber-400 font-semibold uppercase tracking-wide">Opinions</p>
@ -428,22 +428,22 @@ export function BankProfileView() {
)}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Personality Chart */}
{/* Disposition Chart */}
<Card>
<CardHeader className="pb-2">
<CardTitle className="flex items-center gap-2 text-lg">
<Brain className="w-5 h-5 text-primary" />
Personality Profile
Disposition Profile
</CardTitle>
<CardDescription>Big Five personality traits that influence responses</CardDescription>
<CardDescription>Big Five disposition traits that influence responses</CardDescription>
</CardHeader>
<CardContent>
{profile && (
<PersonalityRadarChart
personality={profile.personality}
<DispositionRadarChart
disposition={profile.disposition}
editMode={editMode}
editPersonality={editPersonality}
onEditChange={(trait, value) => setEditPersonality(prev => ({ ...prev, [trait]: value }))}
editDisposition={editDisposition}
onEditChange={(trait, value) => setEditDisposition(prev => ({ ...prev, [trait]: value }))}
/>
)}
</CardContent>

View file

@ -11,7 +11,7 @@ import { Copy, Check, Calendar, ZoomIn, ZoomOut, ChevronLeft, ChevronRight, Chev
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { MemoryDetailPanel } from './memory-detail-panel';
type FactType = 'world' | 'interactions' | 'opinion';
type FactType = 'world' | 'experience' | 'opinion';
type ViewMode = 'graph' | 'table' | 'timeline';
interface DataViewProps {

View file

@ -18,7 +18,7 @@ import { MemoryDetailPanel } from './memory-detail-panel';
type Phase = 'retrieval' | 'rrf' | 'rerank' | 'final' | 'json';
type RetrievalMethod = 'semantic' | 'bm25' | 'graph' | 'temporal';
type FactType = 'world' | 'interactions' | 'opinion';
type FactType = 'world' | 'experience' | 'opinion';
type Budget = 'low' | 'mid' | 'high';
@ -227,7 +227,7 @@ export function SearchDebugView() {
<TableHead><ColumnHeader label="Rank" tooltip="Position in this retrieval method's results" /></TableHead>
<TableHead><ColumnHeader label="Text" tooltip="The memory content" /></TableHead>
{pane.factTypes.length > 1 && (
<TableHead><ColumnHeader label="Type" tooltip="Fact type (world, bank, opinion)" /></TableHead>
<TableHead><ColumnHeader label="Type" tooltip="Fact type (world, experience, opinion)" /></TableHead>
)}
<TableHead><ColumnHeader label="Score" tooltip={scoreTooltip} /></TableHead>
</TableRow>
@ -564,7 +564,7 @@ export function SearchDebugView() {
<div>
<label className="block text-sm font-bold mb-2 text-accent-foreground">Fact Types:</label>
<div className="flex flex-col gap-2">
{(['world', 'interactions', 'opinion'] as FactType[]).map((ft) => (
{(['world', 'experience', 'opinion'] as FactType[]).map((ft) => (
<div key={ft} className="flex items-center gap-2">
<Checkbox
id={`${pane.id}-${ft}`}

View file

@ -156,7 +156,7 @@ export function ThinkView() {
(() => {
// Group facts by type
const worldFacts = result.based_on.filter((f: any) => f.type === 'world');
const interactionsFacts = result.based_on.filter((f: any) => f.type === 'interactions');
const experienceFacts = result.based_on.filter((f: any) => f.type === 'experience');
const opinionFacts = result.based_on.filter((f: any) => f.type === 'opinion');
return (
@ -184,13 +184,13 @@ export function ThinkView() {
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-base">Interactions</CardTitle>
<CardTitle className="text-base">Experience</CardTitle>
<CardDescription className="text-xs">Conversations & Events</CardDescription>
</CardHeader>
<CardContent>
{interactionsFacts.length > 0 ? (
{experienceFacts.length > 0 ? (
<ul className="text-sm space-y-2">
{interactionsFacts.map((fact: any, i: number) => (
{experienceFacts.map((fact: any, i: number) => (
<li key={i} className="p-2 bg-muted rounded">
{fact.text}
{fact.context && <div className="text-xs text-muted-foreground mt-1">{fact.context}</div>}

View file

@ -179,7 +179,7 @@ export class ControlPlaneClient {
return this.fetchApi<{
bank_id: string;
name: string;
personality: {
disposition: {
openness: number;
conscientiousness: number;
extraversion: number;
@ -196,7 +196,7 @@ export class ControlPlaneClient {
*/
async updateBankProfile(bankId: string, profile: {
name?: string;
personality?: {
disposition?: {
openness: number;
conscientiousness: number;
extraversion: number;

View file

@ -15,12 +15,12 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client
## What Are Opinions?
Opinions are beliefs formed by the memory bank based on evidence and personality. Unlike world facts (objective information received) or interactions (conversations and events), opinions are **judgments** with confidence scores.
Opinions are beliefs formed by the memory bank based on evidence and personality. Unlike world facts (objective information received) or experience (conversations and events), opinions are **judgments** with confidence scores.
| Type | Example | Confidence |
|------|---------|------------|
| World Fact | "Python was created in 1991" | — |
| Interactions | "I recommended Python to Bob" | — |
| Experience | "I recommended Python to Bob" | — |
| Opinion | "Python is the best language for data science" | 0.85 |
## How Opinions Form

View file

@ -52,7 +52,7 @@ hindsight memory search my-bank "What does Alice do?"
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | string | required | Natural language query |
| `types` | list | all | Filter: `world`, `interactions`, `opinion` |
| `types` | list | all | Filter: `world`, `experience`, `opinion` |
| `budget` | string | "mid" | Budget level: "low", "mid", "high" |
| `max_tokens` | int | 4096 | Token budget for results |
@ -63,7 +63,7 @@ hindsight memory search my-bank "What does Alice do?"
results = client.recall(
bank_id="my-bank",
query="What does Alice do?",
types=["world", "interactions"],
types=["world", "experience"],
budget="high",
max_tokens=8000
)
@ -94,7 +94,7 @@ For more control, use the full-featured recall method:
response = client.recall_memories(
bank_id="my-bank",
query="What does Alice do?",
types=["world", "interactions"],
types=["world", "experience"],
budget="high",
max_tokens=8000,
trace=True,
@ -119,7 +119,7 @@ if "entities" in response:
// Full response with trace info
const response = await client.recallMemories('my-bank', {
query: 'What does Alice do?',
types: ['world', 'interactions'],
types: ['world', 'experience'],
budget: 'high',
maxTokens: 8000,
trace: true
@ -184,11 +184,11 @@ world_facts = client.recall(
types=["world"]
)
# Only interactions (conversations and events)
interactions = client.recall(
# Only experience (conversations and events)
experience = client.recall(
bank_id="my-bank",
query="What have I recommended?",
types=["interactions"]
types=["experience"]
)
# Only opinions (formed beliefs)
@ -198,11 +198,11 @@ opinions = client.recall(
types=["opinion"]
)
# World facts and interactions (exclude opinions)
# World facts and experience (exclude opinions)
facts = client.recall(
bank_id="my-bank",
query="What happened?",
types=["world", "interactions"]
types=["world", "experience"]
)
```
@ -211,7 +211,7 @@ facts = client.recall(
```bash
hindsight memory search my-bank "Python" --fact-type opinion
hindsight memory search my-bank "Alice" --fact-type world,interactions
hindsight memory search my-bank "Alice" --fact-type world,experience
```
</TabItem>

View file

@ -2,9 +2,9 @@
sidebar_position: 4
---
# Reflect: How Hindsight Reasons with Personality
# Reflect: How Hindsight Reasons with Disposition
When you call `reflect()`, Hindsight doesn't just retrieve facts — it **reasons** about them through the lens of the bank's unique personality, forming new opinions and generating contextual responses.
When you call `reflect()`, Hindsight doesn't just retrieve facts — it **reasons** about them through the lens of the bank's unique disposition, forming new opinions and generating contextual responses.
## Why Reflect?
@ -16,7 +16,7 @@ Without reflect:
- **No consistent character**: "Should we adopt remote work?" gets a different answer each time based on the LLM's randomness
- **No opinion formation**: The system never develops beliefs based on accumulated evidence
- **No reasoning context**: Responses don't reflect what the bank has learned or its perspective
- **Generic responses**: Every AI sounds the same — no personality, no point of view
- **Generic responses**: Every AI sounds the same — no disposition, no point of view
### The Value
@ -31,7 +31,7 @@ With reflect:
| Use `recall()` when... | Use `reflect()` when... |
|------------------------|-------------------------|
| You need raw facts | You need reasoned interpretation |
| You're building your own reasoning | You want personality-consistent responses |
| You're building your own reasoning | You want disposition-consistent responses |
| You need maximum control | You want the bank to "think" for itself |
| Simple fact lookup | Forming recommendations or opinions |
@ -44,16 +44,16 @@ With reflect:
## The Reflect Process
1. **Recall** relevant memories based on the query
2. **Load** the bank's personality traits and background
3. **Reason** about the memories through the personality lens
2. **Load** the bank's disposition traits and background
3. **Reason** about the memories through the disposition lens
4. **Form** new opinions with confidence scores
5. **Return** response, sources, and any new beliefs
---
## Personality Framework (CARA)
## Disposition Framework (CARA)
When you create a memory bank, you can configure its personality using **Big Five traits**. These traits influence how the bank interprets information and forms opinions:
When you create a memory bank, you can configure its disposition using **Big Five traits**. These traits influence how the bank interprets information and forms opinions:
You can also provide a natural language **background** that describes the bank's identity and perspective, which shapes how these traits are applied.
@ -74,7 +74,7 @@ client.create_bank(
bank_id="my-bank",
background="I am a senior software architect with 15 years of distributed "
"systems experience. I prefer simplicity over cutting-edge technology.",
personality={
disposition={
"openness": 0.3, # Prefers proven methods
"conscientiousness": 0.9, # Highly organized
# ... other traits
@ -82,28 +82,28 @@ client.create_bank(
)
```
The background provides context that shapes how personality traits are applied:
The background provides context that shapes how disposition traits are applied:
- "I prefer simplicity" + low openness → consistently favors established solutions
- "15 years experience" → responses reference this expertise
- First-person perspective → creates consistent voice
### Bias Strength
The `bias_strength` parameter (0-1) controls how much personality influences reasoning:
The `bias_strength` parameter (0-1) controls how much disposition influences reasoning:
- **0.0**: Purely evidence-based
- **0.5**: Balanced personality and evidence
- **1.0**: Strongly personality-driven
- **0.5**: Balanced disposition and evidence
- **1.0**: Strongly disposition-driven
---
## Opinion Formation
When `reflect()` encounters a question that warrants forming an opinion, personality shapes the response.
When `reflect()` encounters a question that warrants forming an opinion, disposition shapes the response.
### Same Facts, Different Opinions
Two banks with different personalities, given identical facts about remote work:
Two banks with different dispositions, given identical facts about remote work:
**Bank A** (high openness, low conscientiousness):
> "Remote work unlocks creative flexibility and spontaneous innovation. The freedom to work from anywhere enables breakthrough thinking."
@ -111,7 +111,7 @@ Two banks with different personalities, given identical facts about remote work:
**Bank B** (low openness, high conscientiousness):
> "Remote work lacks the structure and accountability needed for consistent performance. In-person collaboration is more reliable."
**Same facts → Different conclusions** because personality shapes interpretation.
**Same facts → Different conclusions** because disposition shapes interpretation.
---
@ -138,9 +138,9 @@ This **continuous learning** ensures recommendations stay current with real-worl
---
## Personality Presets by Use Case
## Disposition Presets by Use Case
Different use cases benefit from different personality configurations:
Different use cases benefit from different disposition configurations:
| Use Case | Recommended Traits | Why |
|----------|-------------------|-----|
@ -157,7 +157,7 @@ Different use cases benefit from different personality configurations:
When you call `reflect()`:
**Returns:**
- **Response text**Personality-influenced answer
- **Response text**Disposition-influenced answer
- **Based on** — Which memories were used (with relevance scores)
**Example:**
@ -177,16 +177,16 @@ When you call `reflect()`:
---
## Why Personality Matters
## Why Disposition Matters
Without personality, all AI assistants sound the same. With personality:
Without disposition, all AI assistants sound the same. With disposition:
- **Customer support bots** can be diplomatic and empathetic
- **Code review assistants** can be direct and thorough
- **Creative assistants** can be open to unconventional ideas
- **Risk analysts** can be appropriately cautious
Personality creates **consistent character** across conversations while allowing opinions to **evolve with evidence**.
Disposition creates **consistent character** across conversations while allowing opinions to **evolve with evidence**.
---

View file

@ -59,12 +59,12 @@ This means search results include the full context, not disconnected fragments.
## Two Types of Facts
Hindsight distinguishes between **world** facts (about others) and **interactions** (conversations and events):
Hindsight distinguishes between **world** facts (about others) and **experience** (conversations and events):
| Type | Description | Example |
|-----------------|-----------------------------------|---------|
| **world** | Facts about people, places, things | "Alice works at Google" |
| **interactions** | Conversations and events | "I recommended Python to Alice" |
| **experience** | Conversations and events | "I recommended Python to Alice" |
This separation is important for `reflect()` — the bank can reason about what it knows versus what happened in conversations.

View file

@ -102,7 +102,7 @@ Hindsight is built for AI agents, not humans. Traditional search systems return
**Parameters you control:**
- `max_tokens`: How much memory content to return (default: 4096 tokens)
- `budget`: Budget level for graph traversal (low, mid, high)
- `fact_type`: Filter by world, interactions, opinion, or all
- `fact_type`: Filter by world, experience, opinion, or all
### Additional Context: Chunks and Entity Observations

View file

@ -163,7 +163,7 @@ results = client.recall(
response = client.recall_memories(
bank_id="my-agent",
query="What does Alice do?",
types=["world", "interactions"],
types=["world", "experience"],
budget="mid",
max_tokens=4096,
trace=True,

View file

@ -25,7 +25,7 @@ const sidebars: SidebarsConfig = {
},
{
type: 'doc',
id: 'developer/personality',
id: 'developer/reflect',
label: 'Reflect',
},
{

View file

@ -56,7 +56,7 @@
"/v1/default/banks/{bank_id}/graph": {
"get": {
"summary": "Get memory graph data",
"description": "Retrieve graph data for visualization, optionally filtered by type (world/interactions/opinion). Limited to 1000 most recent items.",
"description": "Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.",
"operationId": "get_graph",
"parameters": [
{
@ -204,7 +204,7 @@
"/v1/default/banks/{bank_id}/memories/recall": {
"post": {
"summary": "Recall memory",
"description": "Recall memory using semantic similarity and spreading activation.\n\n The type parameter is optional and must be one of:\n - 'world': General knowledge about people, places, events, and things that happen\n - 'interactions': Memories about interactions, conversations, actions taken, and tasks performed\n - 'opinion': The bank's formed beliefs, perspectives, and viewpoints\n\n Set include_entities=true to get entity observations alongside recall results.",
"description": "Recall memory using semantic similarity and spreading activation.\n\n The type parameter is optional and must be one of:\n - 'world': General knowledge about people, places, events, and things that happen\n - 'experience': Memories about experience, conversations, actions taken, and tasks performed\n - 'opinion': The bank's formed beliefs, perspectives, and viewpoints\n\n Set include_entities=true to get entity observations alongside recall results.",
"operationId": "recall_memories",
"parameters": [
{
@ -254,7 +254,7 @@
"/v1/default/banks/{bank_id}/reflect": {
"post": {
"summary": "Reflect and generate answer",
"description": "Reflect and formulate an answer using bank identity, world facts, and opinions.\n\n This endpoint:\n 1. Retrieves interactions (conversations and events)\n 2. Retrieves world facts relevant to the query\n 3. Retrieves existing opinions (bank's perspectives)\n 4. Uses LLM to formulate a contextual answer\n 5. Extracts and stores any new opinions formed\n 6. Returns plain text answer, the facts used, and new opinions",
"description": "Reflect and formulate an answer using bank identity, world facts, and opinions.\n\n This endpoint:\n 1. Retrieves experience (conversations and events)\n 2. Retrieves world facts relevant to the query\n 3. Retrieves existing opinions (bank's perspectives)\n 4. Uses LLM to formulate a contextual answer\n 5. Extracts and stores any new opinions formed\n 6. Returns plain text answer, the facts used, and new opinions",
"operationId": "reflect",
"parameters": [
{
@ -806,7 +806,7 @@
"/v1/default/banks/{bank_id}/profile": {
"get": {
"summary": "Get memory bank profile",
"description": "Get personality traits and background for a memory bank. Auto-creates agent with defaults if not exists.",
"description": "Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.",
"operationId": "get_bank_profile",
"parameters": [
{
@ -843,9 +843,9 @@
}
},
"put": {
"summary": "Update memory bank personality",
"description": "Update bank's Big Five personality traits and bias strength",
"operationId": "update_bank_personality",
"summary": "Update memory bank disposition",
"description": "Update bank's Big Five disposition traits and bias strength",
"operationId": "update_bank_disposition",
"parameters": [
{
"name": "bank_id",
@ -862,7 +862,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdatePersonalityRequest"
"$ref": "#/components/schemas/UpdateDispositionRequest"
}
}
}
@ -894,7 +894,7 @@
"/v1/default/banks/{bank_id}/background": {
"post": {
"summary": "Add/merge memory bank background",
"description": "Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers personality traits.",
"description": "Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.",
"operationId": "add_bank_background",
"parameters": [
{
@ -944,7 +944,7 @@
"/v1/default/banks/{bank_id}": {
"put": {
"summary": "Create or update memory bank",
"description": "Create a new agent or update existing agent with personality and background. Auto-fills missing fields with defaults.",
"description": "Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.",
"operationId": "create_or_update_bank",
"parameters": [
{
@ -1042,7 +1042,7 @@
},
"delete": {
"summary": "Clear memory bank memories",
"description": "Delete memory units for a memory bank. Optionally filter by type (world, interactions, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.",
"description": "Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (personality and background) will be preserved.",
"operationId": "clear_bank_memories",
"parameters": [
{
@ -1067,10 +1067,10 @@
"type": "null"
}
],
"description": "Optional fact type filter (world, interactions, opinion)",
"description": "Optional fact type filter (world, experience, opinion)",
"title": "Type"
},
"description": "Optional fact type filter (world, interactions, opinion)"
"description": "Optional fact type filter (world, experience, opinion)"
}
],
"responses": {
@ -1107,10 +1107,10 @@
"title": "Content",
"description": "New background information to add or merge"
},
"update_personality": {
"update_disposition": {
"type": "boolean",
"title": "Update Personality",
"description": "If true, infer Big Five personality traits from the merged background (default: true)",
"title": "Update Disposition",
"description": "If true, infer Big Five disposition traits from the merged background (default: true)",
"default": true
}
},
@ -1122,7 +1122,7 @@
"description": "Request model for adding/merging background information.",
"example": {
"content": "I was born in Texas",
"update_personality": true
"update_disposition": true
}
},
"BackgroundResponse": {
@ -1131,10 +1131,10 @@
"type": "string",
"title": "Background"
},
"personality": {
"disposition": {
"anyOf": [
{
"$ref": "#/components/schemas/PersonalityTraits"
"$ref": "#/components/schemas/DispositionTraits"
},
{
"type": "null"
@ -1150,7 +1150,7 @@
"description": "Response model for background update.",
"example": {
"background": "I was born in Texas. I am a software engineer with 10 years of experience.",
"personality": {
"disposition": {
"agreeableness": 0.8,
"bias_strength": 0.6,
"conscientiousness": 0.6,
@ -1170,8 +1170,8 @@
"type": "string",
"title": "Name"
},
"personality": {
"$ref": "#/components/schemas/PersonalityTraits"
"disposition": {
"$ref": "#/components/schemas/DispositionTraits"
},
"background": {
"type": "string",
@ -1204,7 +1204,7 @@
"required": [
"bank_id",
"name",
"personality",
"disposition",
"background"
],
"title": "BankListItem",
@ -1232,8 +1232,7 @@
"background": "I am a software engineer",
"bank_id": "user123",
"created_at": "2024-01-15T10:30:00Z",
"name": "Alice",
"personality": {
"disposition": {
"agreeableness": 0.5,
"bias_strength": 0.5,
"conscientiousness": 0.5,
@ -1241,6 +1240,7 @@
"neuroticism": 0.5,
"openness": 0.5
},
"name": "Alice",
"updated_at": "2024-01-16T14:20:00Z"
}
]
@ -1256,8 +1256,8 @@
"type": "string",
"title": "Name"
},
"personality": {
"$ref": "#/components/schemas/PersonalityTraits"
"disposition": {
"$ref": "#/components/schemas/DispositionTraits"
},
"background": {
"type": "string",
@ -1268,7 +1268,7 @@
"required": [
"bank_id",
"name",
"personality",
"disposition",
"background"
],
"title": "BankProfileResponse",
@ -1276,15 +1276,15 @@
"example": {
"background": "I am a software engineer with 10 years of experience in startups",
"bank_id": "user123",
"name": "Alice",
"personality": {
"disposition": {
"agreeableness": 0.7,
"bias_strength": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
"neuroticism": 0.3,
"openness": 0.8
}
},
"name": "Alice"
}
},
"Budget": {
@ -1400,10 +1400,10 @@
],
"title": "Name"
},
"personality": {
"disposition": {
"anyOf": [
{
"$ref": "#/components/schemas/PersonalityTraits"
"$ref": "#/components/schemas/DispositionTraits"
},
{
"type": "null"
@ -1427,15 +1427,15 @@
"description": "Request model for creating/updating a bank.",
"example": {
"background": "I am a creative software engineer with 10 years of experience",
"name": "Alice",
"personality": {
"disposition": {
"agreeableness": 0.7,
"bias_strength": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
"neuroticism": 0.3,
"openness": 0.8
}
},
"name": "Alice"
}
},
"DeleteResponse": {
@ -1455,6 +1455,71 @@
"success": true
}
},
"DispositionTraits": {
"properties": {
"openness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Openness",
"description": "Openness to experience (0-1)"
},
"conscientiousness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Conscientiousness",
"description": "Conscientiousness (0-1)"
},
"extraversion": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Extraversion",
"description": "Extraversion (0-1)"
},
"agreeableness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Agreeableness",
"description": "Agreeableness (0-1)"
},
"neuroticism": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Neuroticism",
"description": "Neuroticism (0-1)"
},
"bias_strength": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Bias Strength",
"description": "How strongly disposition influences opinions (0-1)"
}
},
"type": "object",
"required": [
"openness",
"conscientiousness",
"extraversion",
"agreeableness",
"neuroticism",
"bias_strength"
],
"title": "DispositionTraits",
"description": "Disposition traits based on Big Five model.",
"example": {
"agreeableness": 0.7,
"bias_strength": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
"neuroticism": 0.3,
"openness": 0.8
}
},
"DocumentResponse": {
"properties": {
"id": {
@ -2084,71 +2149,6 @@
"value": "slack"
}
},
"PersonalityTraits": {
"properties": {
"openness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Openness",
"description": "Openness to experience (0-1)"
},
"conscientiousness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Conscientiousness",
"description": "Conscientiousness (0-1)"
},
"extraversion": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Extraversion",
"description": "Extraversion (0-1)"
},
"agreeableness": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Agreeableness",
"description": "Agreeableness (0-1)"
},
"neuroticism": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Neuroticism",
"description": "Neuroticism (0-1)"
},
"bias_strength": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Bias Strength",
"description": "How strongly personality influences opinions (0-1)"
}
},
"type": "object",
"required": [
"openness",
"conscientiousness",
"extraversion",
"agreeableness",
"neuroticism",
"bias_strength"
],
"title": "PersonalityTraits",
"description": "Personality traits based on Big Five model.",
"example": {
"agreeableness": 0.7,
"bias_strength": 0.7,
"conscientiousness": 0.6,
"extraversion": 0.5,
"neuroticism": 0.3,
"openness": 0.8
}
},
"RecallRequest": {
"properties": {
"query": {
@ -2242,7 +2242,7 @@
"trace": true,
"types": [
"world",
"interactions"
"experience"
]
}
},
@ -2677,7 +2677,7 @@
{
"id": "456",
"text": "I discussed AI applications last week",
"type": "interactions"
"type": "experience"
}
],
"text": "Based on my understanding, AI is a transformative technology..."
@ -2757,18 +2757,18 @@
"success": true
}
},
"UpdatePersonalityRequest": {
"UpdateDispositionRequest": {
"properties": {
"personality": {
"$ref": "#/components/schemas/PersonalityTraits"
"disposition": {
"$ref": "#/components/schemas/DispositionTraits"
}
},
"type": "object",
"required": [
"personality"
"disposition"
],
"title": "UpdatePersonalityRequest",
"description": "Request model for updating personality traits."
"title": "UpdateDispositionRequest",
"description": "Request model for updating disposition traits."
},
"ValidationError": {
"properties": {