simile 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl

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

Potentially problematic release.


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

simile/client.py CHANGED
@@ -10,7 +10,7 @@ from .models import (
10
10
  MCGenerationRequest, MCGenerationResponse,
11
11
  CreatePopulationPayload, CreateAgentPayload, CreateDataItemPayload, UpdateDataItemPayload,
12
12
  InitialDataItemPayload,
13
- SurveySessionCreateResponse
13
+ SurveySessionCreateResponse, SurveySessionDetailResponse
14
14
  )
15
15
  from .resources import Agent, SurveySession
16
16
  from .exceptions import (
@@ -94,13 +94,25 @@ class Simile:
94
94
  json={"agent_id": str(agent_id)},
95
95
  response_model=SurveySessionCreateResponse
96
96
  )
97
+
98
+ # Create and return a SurveySession object
97
99
  return SurveySession(
98
- id=response_data.id,
99
- agent_id=response_data.agent_id,
100
+ id=response_data.id,
101
+ agent_id=response_data.agent_id,
100
102
  status=response_data.status,
101
103
  client=self
102
104
  )
103
105
 
106
+ async def get_survey_session(self, session_id: Union[str, uuid.UUID]) -> SurveySessionDetailResponse:
107
+ """Retrieves detailed information about a survey session including typed conversation history."""
108
+ endpoint = f"sessions/{str(session_id)}"
109
+ response_data = await self._request(
110
+ "GET",
111
+ endpoint,
112
+ response_model=SurveySessionDetailResponse
113
+ )
114
+ return response_data
115
+
104
116
  async def create_population(self, name: str, description: Optional[str] = None) -> Population:
105
117
  """Creates a new population."""
106
118
  payload = CreatePopulationPayload(name=name, description=description)
simile/models.py CHANGED
@@ -1,6 +1,7 @@
1
- from typing import List, Dict, Any, Optional
2
- from pydantic import BaseModel, Field
1
+ from typing import List, Dict, Any, Optional, Union, Literal
2
+ from pydantic import BaseModel, Field, validator
3
3
  from datetime import datetime
4
+ from enum import Enum
4
5
  import uuid
5
6
 
6
7
 
@@ -61,7 +62,8 @@ class DeletionResponse(BaseModel):
61
62
  # --- Generation Operation Models ---
62
63
  class QualGenerationRequest(BaseModel):
63
64
  question: str
64
- image_url: Optional[str] = None
65
+ image_url: Optional[str] = None # For backward compatibility
66
+ images: Optional[Dict[str, str]] = None # Dict of {description: url} for multiple images
65
67
 
66
68
  class QualGenerationResponse(BaseModel):
67
69
  question: str
@@ -77,15 +79,80 @@ class MCGenerationResponse(BaseModel):
77
79
  options: List[str]
78
80
  chosen_option: str
79
81
 
82
+ class AddContextRequest(BaseModel):
83
+ context: str
84
+
85
+ class AddContextResponse(BaseModel):
86
+ message: str
87
+ session_id: uuid.UUID
88
+
80
89
 
81
90
  # --- Survey Session Models ---
82
- class ConversationTurn(BaseModel):
83
- type: str # "qual" or "mc"
84
- question: str
85
- options: Optional[List[str]] = None
86
- answer: Optional[str] = None
87
- chosen_option: Optional[str] = None
88
- timestamp: datetime
91
+ class TurnType(str, Enum):
92
+ """Enum for different types of conversation turns."""
93
+ CONTEXT = "context"
94
+ IMAGE = "image"
95
+ QUALITATIVE_QUESTION = "qualitative_question"
96
+ MULTIPLE_CHOICE_QUESTION = "multiple_choice_question"
97
+
98
+
99
+ class BaseTurn(BaseModel):
100
+ """Base model for all conversation turns."""
101
+ timestamp: datetime = Field(default_factory=lambda: datetime.now())
102
+ type: TurnType
103
+
104
+ class Config:
105
+ use_enum_values = True
106
+
107
+
108
+ class ContextTurn(BaseTurn):
109
+ """A context turn that provides background information."""
110
+ type: Literal[TurnType.CONTEXT] = TurnType.CONTEXT
111
+ user_context: str
112
+
113
+
114
+ class ImageTurn(BaseTurn):
115
+ """A standalone image turn (e.g., for context or reference)."""
116
+ type: Literal[TurnType.IMAGE] = TurnType.IMAGE
117
+ image_url: str
118
+ caption: Optional[str] = None
119
+
120
+
121
+ class QualitativeQuestionTurn(BaseTurn):
122
+ """A qualitative question-answer turn."""
123
+ type: Literal[TurnType.QUALITATIVE_QUESTION] = TurnType.QUALITATIVE_QUESTION
124
+ user_question: str
125
+ user_image_url: Optional[str] = None # For backward compatibility
126
+ user_images: Optional[Dict[str, str]] = None # Dict of {description: url} for multiple images
127
+ llm_response: Optional[str] = None
128
+
129
+
130
+ class MultipleChoiceQuestionTurn(BaseTurn):
131
+ """A multiple choice question-answer turn."""
132
+ type: Literal[TurnType.MULTIPLE_CHOICE_QUESTION] = TurnType.MULTIPLE_CHOICE_QUESTION
133
+ user_question: str
134
+ user_options: List[str]
135
+ user_image_url: Optional[str] = None
136
+ llm_chosen_option: Optional[str] = None
137
+
138
+ @validator('user_options')
139
+ def validate_options(cls, v):
140
+ if not v:
141
+ raise ValueError("Multiple choice questions must have at least one option")
142
+ if len(v) < 2:
143
+ raise ValueError("Multiple choice questions should have at least two options")
144
+ return v
145
+
146
+ @validator('llm_chosen_option')
147
+ def validate_chosen_option(cls, v, values):
148
+ if v is not None and 'user_options' in values and v not in values['user_options']:
149
+ raise ValueError(f"Chosen option '{v}' must be one of the provided options")
150
+ return v
151
+
152
+
153
+ # Union type for all possible turn types
154
+ SurveySessionTurn = Union[ContextTurn, ImageTurn, QualitativeQuestionTurn, MultipleChoiceQuestionTurn]
155
+
89
156
 
90
157
  class SurveySessionCreateResponse(BaseModel):
91
158
  id: uuid.UUID # Session ID
@@ -93,6 +160,37 @@ class SurveySessionCreateResponse(BaseModel):
93
160
  created_at: datetime
94
161
  status: str
95
162
 
163
+
164
+ class SurveySessionDetailResponse(BaseModel):
165
+ """Detailed survey session response with typed conversation turns."""
166
+ id: uuid.UUID
167
+ agent_id: uuid.UUID
168
+ created_at: datetime
169
+ updated_at: datetime
170
+ status: str
171
+ conversation_history: List[SurveySessionTurn] = Field(default_factory=list)
172
+
173
+ class Config:
174
+ json_encoders = {
175
+ datetime: lambda v: v.isoformat()
176
+ }
177
+
178
+
179
+ class SurveySessionListItemResponse(BaseModel):
180
+ """Summary response for listing survey sessions."""
181
+ id: uuid.UUID
182
+ agent_id: uuid.UUID
183
+ created_at: datetime
184
+ updated_at: datetime
185
+ status: str
186
+ turn_count: int = Field(description="Number of turns in conversation history")
187
+
188
+ class Config:
189
+ json_encoders = {
190
+ datetime: lambda v: v.isoformat()
191
+ }
192
+
193
+
96
194
  class SurveySessionCloseResponse(BaseModel):
97
195
  id: uuid.UUID # Session ID
98
196
  status: str
simile/resources.py CHANGED
@@ -1,20 +1,25 @@
1
1
  import uuid
2
- from typing import TYPE_CHECKING, List, Optional
2
+ from typing import TYPE_CHECKING, List, Optional, Dict
3
3
 
4
4
  from .models import (
5
5
  QualGenerationRequest,
6
6
  QualGenerationResponse,
7
7
  MCGenerationRequest,
8
8
  MCGenerationResponse,
9
- SurveySessionCloseResponse
9
+ SurveySessionCloseResponse,
10
+ AddContextRequest,
11
+ AddContextResponse,
12
+ SurveySessionDetailResponse,
10
13
  )
11
14
 
12
15
  if TYPE_CHECKING:
13
16
  from .client import Simile
14
17
 
18
+
15
19
  class Agent:
16
20
  """Represents an agent and provides methods for interacting with it directly."""
17
- def __init__(self, agent_id: uuid.UUID, client: 'Simile'):
21
+
22
+ def __init__(self, agent_id: uuid.UUID, client: "Simile"):
18
23
  self._agent_id = agent_id
19
24
  self._client = client
20
25
 
@@ -22,18 +27,32 @@ class Agent:
22
27
  def id(self) -> uuid.UUID:
23
28
  return self._agent_id
24
29
 
25
- async def generate_qual_response(self, question: str, image_url: Optional[str] = None) -> QualGenerationResponse:
30
+ async def generate_qual_response(
31
+ self, question: str, image_url: Optional[str] = None
32
+ ) -> QualGenerationResponse:
26
33
  """Generates a qualitative response from this agent based on a question."""
27
- return await self._client.generate_qual_response(agent_id=self._agent_id, question=question, image_url=image_url)
34
+ return await self._client.generate_qual_response(
35
+ agent_id=self._agent_id, question=question, image_url=image_url
36
+ )
28
37
 
29
- async def generate_mc_response(self, question: str, options: List[str], image_url: Optional[str] = None) -> MCGenerationResponse:
38
+ async def generate_mc_response(
39
+ self, question: str, options: List[str], image_url: Optional[str] = None
40
+ ) -> MCGenerationResponse:
30
41
  """Generates a multiple-choice response from this agent."""
31
- return await self._client.generate_mc_response(agent_id=self._agent_id, question=question, options=options, image_url=image_url)
42
+ return await self._client.generate_mc_response(
43
+ agent_id=self._agent_id,
44
+ question=question,
45
+ options=options,
46
+ image_url=image_url,
47
+ )
32
48
 
33
49
 
34
50
  class SurveySession:
35
51
  """Represents an active survey session with an agent, allowing for contextual multi-turn generation."""
36
- def __init__(self, id: uuid.UUID, agent_id: uuid.UUID, status: str, client: 'Simile'):
52
+
53
+ def __init__(
54
+ self, id: uuid.UUID, agent_id: uuid.UUID, status: str, client: "Simile"
55
+ ):
37
56
  self._id = id
38
57
  self._agent_id = agent_id
39
58
  self._status = status
@@ -51,33 +70,57 @@ class SurveySession:
51
70
  def status(self) -> str:
52
71
  return self._status
53
72
 
54
- async def generate_qual_response(self, question: str, image_url: Optional[str] = None) -> QualGenerationResponse:
73
+ async def get_details(self) -> SurveySessionDetailResponse:
74
+ """Retrieves detailed information about this survey session including typed conversation history."""
75
+ return await self._client.get_survey_session(self._id)
76
+
77
+ async def generate_qual_response(
78
+ self,
79
+ question: str,
80
+ image_url: Optional[str] = None,
81
+ images: Optional[Dict[str, str]] = None,
82
+ ) -> QualGenerationResponse:
55
83
  """Generates a qualitative response within this survey session."""
56
84
  endpoint = f"sessions/{str(self._id)}/qual"
57
- payload = QualGenerationRequest(question=question, image_url=image_url)
85
+ payload = QualGenerationRequest(
86
+ question=question, image_url=image_url, images=images
87
+ )
58
88
  return await self._client._request(
59
89
  "POST",
60
90
  endpoint,
61
- json=payload.model_dump(),
62
- response_model=QualGenerationResponse
91
+ json=payload.model_dump(),
92
+ response_model=QualGenerationResponse,
63
93
  )
64
94
 
65
- async def generate_mc_response(self, question: str, options: List[str], image_url: Optional[str] = None) -> MCGenerationResponse:
95
+ async def generate_mc_response(
96
+ self, question: str, options: List[str], image_url: Optional[str] = None
97
+ ) -> MCGenerationResponse:
66
98
  """Generates a multiple-choice response within this survey session."""
67
99
  endpoint = f"sessions/{str(self._id)}/mc"
68
- payload = MCGenerationRequest(question=question, options=options, image_url=image_url)
100
+ payload = MCGenerationRequest(
101
+ question=question, options=options, image_url=image_url
102
+ )
69
103
  return await self._client._request(
70
104
  "POST",
71
105
  endpoint,
72
- json=payload.model_dump(),
73
- response_model=MCGenerationResponse
106
+ json=payload.model_dump(),
107
+ response_model=MCGenerationResponse,
108
+ )
109
+
110
+ async def add_context(self, ctx: str) -> AddContextResponse:
111
+ """Adds text to the SurveySession without requesting a response."""
112
+ endpoint = f"sessions/{str(self._id)}/context"
113
+ payload = AddContextRequest(context=ctx)
114
+ return await self._client._request(
115
+ "POST",
116
+ endpoint,
117
+ json=payload.model_dump(),
118
+ response_model=AddContextResponse,
74
119
  )
75
120
 
76
121
  async def close(self) -> SurveySessionCloseResponse:
77
122
  """Closes this survey session on the server."""
78
123
  endpoint = f"sessions/{str(self._id)}/close"
79
124
  return await self._client._request(
80
- "POST",
81
- endpoint,
82
- response_model=SurveySessionCloseResponse
125
+ "POST", endpoint, response_model=SurveySessionCloseResponse
83
126
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simile
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Package for interfacing with Simile AI agents for simulation
5
5
  Author-email: Simile AI <cqz@simile.ai>
6
6
  License: MIT
@@ -0,0 +1,10 @@
1
+ simile/__init__.py,sha256=2OZ1LQIkAEtSs0EI5Fzlg7QGKduCgCe_nTh9FfIuHlQ,865
2
+ simile/client.py,sha256=Bw9KML7S-V8gB8-ctitDvgesAkgI5w6cqasRL8Z_070,10394
3
+ simile/exceptions.py,sha256=-rJ3KZcpvNRi9JXbDpxWDSL2lU1mEJX2piwYRZvhKmg,1406
4
+ simile/models.py,sha256=gM6QqVySJe6sG-X7deDcpQYo0JMhfxtfZtBHFP-ZqSI,5376
5
+ simile/resources.py,sha256=4SgiA24lYPCZi_DlJZzX-nUbE8rPMoDSPR65VT0YoW0,4181
6
+ simile-0.2.7.dist-info/licenses/LICENSE,sha256=tpxX3bpODfyOQVyEM6kCMvPHFCpkjFDj0AICRqKqOFA,1066
7
+ simile-0.2.7.dist-info/METADATA,sha256=Upzlhf06MRQThgSVZnzls4liEPX4dJrHvYILAJ-uKf0,1276
8
+ simile-0.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ simile-0.2.7.dist-info/top_level.txt,sha256=41lJneubAG4-ZOAs5qn7iDtDb-MDxa6DdvgBKwNX84M,7
10
+ simile-0.2.7.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- simile/__init__.py,sha256=2OZ1LQIkAEtSs0EI5Fzlg7QGKduCgCe_nTh9FfIuHlQ,865
2
- simile/client.py,sha256=_XsrdDHO25Fsnap6uhUlbMrKO8vMJGJaDCeym8xBs8o,9866
3
- simile/exceptions.py,sha256=-rJ3KZcpvNRi9JXbDpxWDSL2lU1mEJX2piwYRZvhKmg,1406
4
- simile/models.py,sha256=SRlQWU4Q1i7f-7rqDl4E84zanMhokpeOq9TD8ks4qtU,2176
5
- simile/resources.py,sha256=jF7sYm7ZjFTpeHYqa69b1rmEbCbuR8IhuXbeHmpsoUw,3176
6
- simile-0.2.5.dist-info/licenses/LICENSE,sha256=tpxX3bpODfyOQVyEM6kCMvPHFCpkjFDj0AICRqKqOFA,1066
7
- simile-0.2.5.dist-info/METADATA,sha256=lkzqUyOA9gQ3Nu1Z8ufnI7U-M6T5iItj50NumhWZ2FI,1276
8
- simile-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- simile-0.2.5.dist-info/top_level.txt,sha256=41lJneubAG4-ZOAs5qn7iDtDb-MDxa6DdvgBKwNX84M,7
10
- simile-0.2.5.dist-info/RECORD,,
File without changes