simile 0.2.6__py3-none-any.whl → 0.2.8__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 +174 -53
- simile/models.py +101 -10
- simile/resources.py +9 -4
- {simile-0.2.6.dist-info → simile-0.2.8.dist-info}/METADATA +1 -1
- simile-0.2.8.dist-info/RECORD +10 -0
- simile-0.2.6.dist-info/RECORD +0 -10
- {simile-0.2.6.dist-info → simile-0.2.8.dist-info}/WHEEL +0 -0
- {simile-0.2.6.dist-info → simile-0.2.8.dist-info}/licenses/LICENSE +0 -0
- {simile-0.2.6.dist-info → simile-0.2.8.dist-info}/top_level.txt +0 -0
simile/client.py
CHANGED
|
@@ -5,21 +5,34 @@ import uuid
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
7
|
from .models import (
|
|
8
|
-
Population,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
Population,
|
|
9
|
+
Agent as AgentModel,
|
|
10
|
+
DataItem,
|
|
11
|
+
DeletionResponse,
|
|
12
|
+
QualGenerationRequest,
|
|
13
|
+
QualGenerationResponse,
|
|
14
|
+
MCGenerationRequest,
|
|
15
|
+
MCGenerationResponse,
|
|
16
|
+
CreatePopulationPayload,
|
|
17
|
+
CreateAgentPayload,
|
|
18
|
+
CreateDataItemPayload,
|
|
19
|
+
UpdateDataItemPayload,
|
|
12
20
|
InitialDataItemPayload,
|
|
13
|
-
SurveySessionCreateResponse
|
|
21
|
+
SurveySessionCreateResponse,
|
|
22
|
+
SurveySessionDetailResponse,
|
|
14
23
|
)
|
|
15
24
|
from .resources import Agent, SurveySession
|
|
16
25
|
from .exceptions import (
|
|
17
|
-
SimileAPIError,
|
|
26
|
+
SimileAPIError,
|
|
27
|
+
SimileAuthenticationError,
|
|
28
|
+
SimileNotFoundError,
|
|
29
|
+
SimileBadRequestError,
|
|
18
30
|
)
|
|
19
31
|
|
|
20
32
|
DEFAULT_BASE_URL = "https://simile-api-3a83be7adae0.herokuapp.com/api/v1"
|
|
21
33
|
TIMEOUT_CONFIG = httpx.Timeout(5.0, read=30.0, write=30.0, pool=30.0)
|
|
22
34
|
|
|
35
|
+
|
|
23
36
|
class Simile:
|
|
24
37
|
APIError = SimileAPIError
|
|
25
38
|
AuthenticationError = SimileAuthenticationError
|
|
@@ -30,16 +43,19 @@ class Simile:
|
|
|
30
43
|
if not api_key:
|
|
31
44
|
raise ValueError("API key is required.")
|
|
32
45
|
self.api_key = api_key
|
|
33
|
-
self.base_url = base_url.rstrip(
|
|
46
|
+
self.base_url = base_url.rstrip("/")
|
|
34
47
|
self._client = AsyncClient(
|
|
35
|
-
headers={"X-API-Key": self.api_key},
|
|
36
|
-
timeout=TIMEOUT_CONFIG
|
|
48
|
+
headers={"X-API-Key": self.api_key}, timeout=TIMEOUT_CONFIG
|
|
37
49
|
)
|
|
38
50
|
|
|
39
|
-
async def _request(
|
|
51
|
+
async def _request(
|
|
52
|
+
self, method: str, endpoint: str, **kwargs
|
|
53
|
+
) -> Union[httpx.Response, BaseModel]:
|
|
40
54
|
url = f"{self.base_url}/{endpoint.lstrip('/')}"
|
|
41
|
-
response_model_cls: Optional[Type[BaseModel]] = kwargs.pop(
|
|
42
|
-
|
|
55
|
+
response_model_cls: Optional[Type[BaseModel]] = kwargs.pop(
|
|
56
|
+
"response_model", None
|
|
57
|
+
)
|
|
58
|
+
|
|
43
59
|
try:
|
|
44
60
|
response = await self._client.request(method, url, **kwargs)
|
|
45
61
|
response.raise_for_status()
|
|
@@ -63,7 +79,9 @@ class Simile:
|
|
|
63
79
|
elif status_code == 400:
|
|
64
80
|
raise SimileBadRequestError(detail=detail)
|
|
65
81
|
else:
|
|
66
|
-
raise SimileAPIError(
|
|
82
|
+
raise SimileAPIError(
|
|
83
|
+
f"API request failed: {e}", status_code=status_code, detail=detail
|
|
84
|
+
)
|
|
67
85
|
except httpx.ConnectTimeout:
|
|
68
86
|
raise SimileAPIError("Connection timed out while trying to connect.")
|
|
69
87
|
except httpx.ReadTimeout:
|
|
@@ -79,7 +97,9 @@ class Simile:
|
|
|
79
97
|
except httpx.DecodingError:
|
|
80
98
|
raise SimileAPIError("Failed to decode the response.")
|
|
81
99
|
except httpx.RequestError as e:
|
|
82
|
-
raise SimileAPIError(
|
|
100
|
+
raise SimileAPIError(
|
|
101
|
+
f"An unknown request error occurred: {type(e).__name__}: {e}"
|
|
102
|
+
)
|
|
83
103
|
|
|
84
104
|
def agent(self, agent_id: uuid.UUID) -> Agent:
|
|
85
105
|
"""Returns an Agent object to interact with a specific agent."""
|
|
@@ -92,108 +112,209 @@ class Simile:
|
|
|
92
112
|
"POST",
|
|
93
113
|
endpoint,
|
|
94
114
|
json={"agent_id": str(agent_id)},
|
|
95
|
-
response_model=SurveySessionCreateResponse
|
|
115
|
+
response_model=SurveySessionCreateResponse,
|
|
96
116
|
)
|
|
117
|
+
|
|
118
|
+
# Create and return a SurveySession object
|
|
97
119
|
return SurveySession(
|
|
98
|
-
id=response_data.id,
|
|
99
|
-
agent_id=response_data.agent_id,
|
|
120
|
+
id=response_data.id,
|
|
121
|
+
agent_id=response_data.agent_id,
|
|
100
122
|
status=response_data.status,
|
|
101
|
-
client=self
|
|
123
|
+
client=self,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
async def get_survey_session_details(
|
|
127
|
+
self, session_id: Union[str, uuid.UUID]
|
|
128
|
+
) -> SurveySessionDetailResponse:
|
|
129
|
+
"""Retrieves detailed information about a survey session including typed conversation history."""
|
|
130
|
+
endpoint = f"sessions/{str(session_id)}"
|
|
131
|
+
response_data = await self._request(
|
|
132
|
+
"GET", endpoint, response_model=SurveySessionDetailResponse
|
|
102
133
|
)
|
|
134
|
+
return response_data
|
|
135
|
+
|
|
136
|
+
async def get_survey_session(
|
|
137
|
+
self, session_id: Union[str, uuid.UUID]
|
|
138
|
+
) -> SurveySession:
|
|
139
|
+
"""Resume an existing survey session by ID and return a SurveySession object."""
|
|
140
|
+
session_details = await self.get_survey_session(session_id)
|
|
103
141
|
|
|
104
|
-
|
|
142
|
+
if session_details.status == "closed":
|
|
143
|
+
raise ValueError(f"Session {session_id} is already closed")
|
|
144
|
+
|
|
145
|
+
return SurveySession(
|
|
146
|
+
id=session_details.id,
|
|
147
|
+
agent_id=session_details.agent_id,
|
|
148
|
+
status=session_details.status,
|
|
149
|
+
client=self,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
async def create_population(
|
|
153
|
+
self, name: str, description: Optional[str] = None
|
|
154
|
+
) -> Population:
|
|
105
155
|
"""Creates a new population."""
|
|
106
156
|
payload = CreatePopulationPayload(name=name, description=description)
|
|
107
|
-
response_data = await self._request(
|
|
157
|
+
response_data = await self._request(
|
|
158
|
+
"POST",
|
|
159
|
+
"populations/create",
|
|
160
|
+
json=payload.model_dump(mode="json", exclude_none=True),
|
|
161
|
+
response_model=Population,
|
|
162
|
+
)
|
|
108
163
|
return response_data
|
|
109
164
|
|
|
110
165
|
async def get_population(self, population_id: Union[str, uuid.UUID]) -> Population:
|
|
111
|
-
response_data = await self._request(
|
|
166
|
+
response_data = await self._request(
|
|
167
|
+
"GET", f"populations/get/{str(population_id)}", response_model=Population
|
|
168
|
+
)
|
|
112
169
|
return response_data
|
|
113
170
|
|
|
114
|
-
async def delete_population(
|
|
115
|
-
|
|
171
|
+
async def delete_population(
|
|
172
|
+
self, population_id: Union[str, uuid.UUID]
|
|
173
|
+
) -> DeletionResponse:
|
|
174
|
+
response_data = await self._request(
|
|
175
|
+
"DELETE",
|
|
176
|
+
f"populations/delete/{str(population_id)}",
|
|
177
|
+
response_model=DeletionResponse,
|
|
178
|
+
)
|
|
116
179
|
return response_data
|
|
117
180
|
|
|
118
|
-
async def get_agents_in_population(
|
|
181
|
+
async def get_agents_in_population(
|
|
182
|
+
self, population_id: Union[str, uuid.UUID]
|
|
183
|
+
) -> List[AgentModel]:
|
|
119
184
|
"""Retrieves all agents belonging to a specific population."""
|
|
120
185
|
endpoint = f"populations/{str(population_id)}/agents"
|
|
121
186
|
raw_response = await self._request("GET", endpoint)
|
|
122
187
|
agents_data_list = raw_response.json()
|
|
123
188
|
return [AgentModel(**data) for data in agents_data_list]
|
|
124
189
|
|
|
125
|
-
async def create_agent(
|
|
190
|
+
async def create_agent(
|
|
191
|
+
self,
|
|
192
|
+
name: str,
|
|
193
|
+
population_id: Optional[Union[str, uuid.UUID]] = None,
|
|
194
|
+
agent_data: Optional[List[Dict[str, Any]]] = None,
|
|
195
|
+
) -> AgentModel:
|
|
126
196
|
"""Creates a new agent, optionally within a population and with initial data items."""
|
|
127
197
|
pop_id_uuid: Optional[uuid.UUID] = None
|
|
128
198
|
if population_id:
|
|
129
|
-
pop_id_uuid =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
199
|
+
pop_id_uuid = (
|
|
200
|
+
uuid.UUID(str(population_id))
|
|
201
|
+
if not isinstance(population_id, uuid.UUID)
|
|
202
|
+
else population_id
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
payload = CreateAgentPayload(
|
|
206
|
+
name=name, population_id=pop_id_uuid, agent_data=agent_data
|
|
207
|
+
)
|
|
208
|
+
response_data = await self._request(
|
|
209
|
+
"POST",
|
|
210
|
+
"agents/create",
|
|
211
|
+
json=payload.model_dump(mode="json", exclude_none=True),
|
|
212
|
+
response_model=AgentModel,
|
|
213
|
+
)
|
|
133
214
|
return response_data
|
|
134
215
|
|
|
135
216
|
async def get_agent(self, agent_id: Union[str, uuid.UUID]) -> AgentModel:
|
|
136
|
-
response_data = await self._request(
|
|
217
|
+
response_data = await self._request(
|
|
218
|
+
"GET", f"agents/get/{str(agent_id)}", response_model=AgentModel
|
|
219
|
+
)
|
|
137
220
|
return response_data
|
|
138
221
|
|
|
139
222
|
async def delete_agent(self, agent_id: Union[str, uuid.UUID]) -> DeletionResponse:
|
|
140
|
-
response_data = await self._request(
|
|
223
|
+
response_data = await self._request(
|
|
224
|
+
"DELETE", f"agents/delete/{str(agent_id)}", response_model=DeletionResponse
|
|
225
|
+
)
|
|
141
226
|
return response_data
|
|
142
227
|
|
|
143
|
-
async def create_data_item(
|
|
228
|
+
async def create_data_item(
|
|
229
|
+
self, agent_id: Union[str, uuid.UUID], data_type: str, content: Any
|
|
230
|
+
) -> DataItem:
|
|
144
231
|
"""Creates a new data item for a specific agent."""
|
|
145
232
|
payload = CreateDataItemPayload(data_type=data_type, content=content)
|
|
146
|
-
response_data = await self._request(
|
|
233
|
+
response_data = await self._request(
|
|
234
|
+
"POST",
|
|
235
|
+
f"data_item/create/{str(agent_id)}",
|
|
236
|
+
json=payload.model_dump(mode="json"),
|
|
237
|
+
response_model=DataItem,
|
|
238
|
+
)
|
|
147
239
|
return response_data
|
|
148
240
|
|
|
149
241
|
async def get_data_item(self, data_item_id: Union[str, uuid.UUID]) -> DataItem:
|
|
150
|
-
response_data = await self._request(
|
|
242
|
+
response_data = await self._request(
|
|
243
|
+
"GET", f"data_item/get/{str(data_item_id)}", response_model=DataItem
|
|
244
|
+
)
|
|
151
245
|
return response_data
|
|
152
246
|
|
|
153
|
-
async def list_data_items(
|
|
247
|
+
async def list_data_items(
|
|
248
|
+
self, agent_id: Union[str, uuid.UUID], data_type: Optional[str] = None
|
|
249
|
+
) -> List[DataItem]:
|
|
154
250
|
params = {}
|
|
155
251
|
if data_type:
|
|
156
252
|
params["data_type"] = data_type
|
|
157
253
|
agent_id_str = str(agent_id)
|
|
158
|
-
raw_response = await self._request(
|
|
159
|
-
|
|
254
|
+
raw_response = await self._request(
|
|
255
|
+
"GET", f"data_item/list/{agent_id_str}", params=params
|
|
256
|
+
)
|
|
257
|
+
return [DataItem(**item) for item in raw_response.json()]
|
|
160
258
|
|
|
161
|
-
async def update_data_item(
|
|
259
|
+
async def update_data_item(
|
|
260
|
+
self, data_item_id: Union[str, uuid.UUID], content: Any
|
|
261
|
+
) -> DataItem:
|
|
162
262
|
"""Updates an existing data item."""
|
|
163
263
|
payload = UpdateDataItemPayload(content=content)
|
|
164
|
-
response_data = await self._request(
|
|
264
|
+
response_data = await self._request(
|
|
265
|
+
"POST",
|
|
266
|
+
f"data_item/update/{str(data_item_id)}",
|
|
267
|
+
json=payload.model_dump(),
|
|
268
|
+
response_model=DataItem,
|
|
269
|
+
)
|
|
165
270
|
return response_data
|
|
166
271
|
|
|
167
|
-
async def delete_data_item(
|
|
168
|
-
|
|
272
|
+
async def delete_data_item(
|
|
273
|
+
self, data_item_id: Union[str, uuid.UUID]
|
|
274
|
+
) -> DeletionResponse:
|
|
275
|
+
response_data = await self._request(
|
|
276
|
+
"DELETE",
|
|
277
|
+
f"data_item/delete/{str(data_item_id)}",
|
|
278
|
+
response_model=DeletionResponse,
|
|
279
|
+
)
|
|
169
280
|
return response_data
|
|
170
281
|
|
|
171
|
-
async def generate_qual_response(
|
|
282
|
+
async def generate_qual_response(
|
|
283
|
+
self, agent_id: uuid.UUID, question: str, image_url: Optional[str] = None
|
|
284
|
+
) -> QualGenerationResponse:
|
|
172
285
|
"""Generates a qualitative response from an agent based on a question."""
|
|
173
286
|
endpoint = f"/generation/qual/{str(agent_id)}"
|
|
174
287
|
request_payload = QualGenerationRequest(question=question, image_url=image_url)
|
|
175
288
|
response_data = await self._request(
|
|
176
|
-
"POST",
|
|
177
|
-
endpoint,
|
|
178
|
-
json=request_payload.model_dump(),
|
|
179
|
-
response_model=QualGenerationResponse
|
|
289
|
+
"POST",
|
|
290
|
+
endpoint,
|
|
291
|
+
json=request_payload.model_dump(),
|
|
292
|
+
response_model=QualGenerationResponse,
|
|
180
293
|
)
|
|
181
294
|
return response_data
|
|
182
295
|
|
|
183
|
-
async def generate_mc_response(
|
|
296
|
+
async def generate_mc_response(
|
|
297
|
+
self,
|
|
298
|
+
agent_id: uuid.UUID,
|
|
299
|
+
question: str,
|
|
300
|
+
options: List[str],
|
|
301
|
+
image_url: Optional[str] = None,
|
|
302
|
+
) -> MCGenerationResponse:
|
|
184
303
|
"""Generates a multiple-choice response from an agent."""
|
|
185
304
|
endpoint = f"generation/mc/{str(agent_id)}"
|
|
186
|
-
request_payload = MCGenerationRequest(
|
|
305
|
+
request_payload = MCGenerationRequest(
|
|
306
|
+
question=question, options=options, image_url=image_url
|
|
307
|
+
)
|
|
187
308
|
response_data = await self._request(
|
|
188
|
-
"POST",
|
|
189
|
-
endpoint,
|
|
190
|
-
json=request_payload.model_dump(),
|
|
191
|
-
response_model=MCGenerationResponse
|
|
309
|
+
"POST",
|
|
310
|
+
endpoint,
|
|
311
|
+
json=request_payload.model_dump(),
|
|
312
|
+
response_model=MCGenerationResponse,
|
|
192
313
|
)
|
|
193
314
|
return response_data
|
|
194
315
|
|
|
195
316
|
async def aclose(self):
|
|
196
|
-
await self._client.aclose()
|
|
317
|
+
await self._client.aclose()
|
|
197
318
|
|
|
198
319
|
async def __aenter__(self):
|
|
199
320
|
return self
|
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
|
|
@@ -86,13 +88,71 @@ class AddContextResponse(BaseModel):
|
|
|
86
88
|
|
|
87
89
|
|
|
88
90
|
# --- Survey Session Models ---
|
|
89
|
-
class
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
+
|
|
96
156
|
|
|
97
157
|
class SurveySessionCreateResponse(BaseModel):
|
|
98
158
|
id: uuid.UUID # Session ID
|
|
@@ -100,6 +160,37 @@ class SurveySessionCreateResponse(BaseModel):
|
|
|
100
160
|
created_at: datetime
|
|
101
161
|
status: str
|
|
102
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
|
+
|
|
103
194
|
class SurveySessionCloseResponse(BaseModel):
|
|
104
195
|
id: uuid.UUID # Session ID
|
|
105
196
|
status: str
|
simile/resources.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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,
|
|
@@ -8,7 +8,8 @@ from .models import (
|
|
|
8
8
|
MCGenerationResponse,
|
|
9
9
|
SurveySessionCloseResponse,
|
|
10
10
|
AddContextRequest,
|
|
11
|
-
AddContextResponse
|
|
11
|
+
AddContextResponse,
|
|
12
|
+
SurveySessionDetailResponse
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
@@ -53,10 +54,14 @@ class SurveySession:
|
|
|
53
54
|
def status(self) -> str:
|
|
54
55
|
return self._status
|
|
55
56
|
|
|
56
|
-
async def
|
|
57
|
+
async def get_details(self) -> SurveySessionDetailResponse:
|
|
58
|
+
"""Retrieves detailed information about this survey session including typed conversation history."""
|
|
59
|
+
return await self._client.get_survey_session(self._id)
|
|
60
|
+
|
|
61
|
+
async def generate_qual_response(self, question: str, image_url: Optional[str] = None, images: Optional[Dict[str, str]] = None) -> QualGenerationResponse:
|
|
57
62
|
"""Generates a qualitative response within this survey session."""
|
|
58
63
|
endpoint = f"sessions/{str(self._id)}/qual"
|
|
59
|
-
payload = QualGenerationRequest(question=question, image_url=image_url)
|
|
64
|
+
payload = QualGenerationRequest(question=question, image_url=image_url, images=images)
|
|
60
65
|
return await self._client._request(
|
|
61
66
|
"POST",
|
|
62
67
|
endpoint,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
simile/__init__.py,sha256=2OZ1LQIkAEtSs0EI5Fzlg7QGKduCgCe_nTh9FfIuHlQ,865
|
|
2
|
+
simile/client.py,sha256=6gtzniCdx4bfpseO448ViZa0CGz1CdQDPGXM3VBaRyg,11826
|
|
3
|
+
simile/exceptions.py,sha256=-rJ3KZcpvNRi9JXbDpxWDSL2lU1mEJX2piwYRZvhKmg,1406
|
|
4
|
+
simile/models.py,sha256=gM6QqVySJe6sG-X7deDcpQYo0JMhfxtfZtBHFP-ZqSI,5376
|
|
5
|
+
simile/resources.py,sha256=KPSmcX6cgVfOCPvL1eD5zc9fvOw5n4oe6pOieuzp8zg,3982
|
|
6
|
+
simile-0.2.8.dist-info/licenses/LICENSE,sha256=tpxX3bpODfyOQVyEM6kCMvPHFCpkjFDj0AICRqKqOFA,1066
|
|
7
|
+
simile-0.2.8.dist-info/METADATA,sha256=xic3erPzu6K041_zHaHDM8na8HkHGPIRKBcUsf4mH_g,1276
|
|
8
|
+
simile-0.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
simile-0.2.8.dist-info/top_level.txt,sha256=41lJneubAG4-ZOAs5qn7iDtDb-MDxa6DdvgBKwNX84M,7
|
|
10
|
+
simile-0.2.8.dist-info/RECORD,,
|
simile-0.2.6.dist-info/RECORD
DELETED
|
@@ -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=dBqH3mVcjvNpOTPV5CBwXjkqZrgmgvZYU1r5ZUqI878,2311
|
|
5
|
-
simile/resources.py,sha256=AeT8547YChPGGSIkhZ2bfN73BhDh1c3OEopJqGIlGE8,3650
|
|
6
|
-
simile-0.2.6.dist-info/licenses/LICENSE,sha256=tpxX3bpODfyOQVyEM6kCMvPHFCpkjFDj0AICRqKqOFA,1066
|
|
7
|
-
simile-0.2.6.dist-info/METADATA,sha256=Ny1lEKybPGZ_CC9q3ibcAfU4AtG2SKVg_jol8QDsbYE,1276
|
|
8
|
-
simile-0.2.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
simile-0.2.6.dist-info/top_level.txt,sha256=41lJneubAG4-ZOAs5qn7iDtDb-MDxa6DdvgBKwNX84M,7
|
|
10
|
-
simile-0.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|