simile 0.2.7__tar.gz → 0.2.8__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simile
3
- Version: 0.2.7
3
+ Version: 0.2.8
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simile"
7
- version = "0.2.7"
7
+ version = "0.2.8"
8
8
  authors = [
9
9
  { name="Simile AI", email="cqz@simile.ai" },
10
10
  ]
@@ -5,21 +5,34 @@ import uuid
5
5
  from pydantic import BaseModel
6
6
 
7
7
  from .models import (
8
- Population, Agent as AgentModel, DataItem, DeletionResponse,
9
- QualGenerationRequest, QualGenerationResponse,
10
- MCGenerationRequest, MCGenerationResponse,
11
- CreatePopulationPayload, CreateAgentPayload, CreateDataItemPayload, UpdateDataItemPayload,
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, SurveySessionDetailResponse
21
+ SurveySessionCreateResponse,
22
+ SurveySessionDetailResponse,
14
23
  )
15
24
  from .resources import Agent, SurveySession
16
25
  from .exceptions import (
17
- SimileAPIError, SimileAuthenticationError, SimileNotFoundError, SimileBadRequestError
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(self, method: str, endpoint: str, **kwargs) -> Union[httpx.Response, BaseModel]:
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("response_model", None)
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(f"API request failed: {e}", status_code=status_code, detail=detail)
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(f"An unknown request error occurred: {type(e).__name__}: {e}")
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,120 +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
  )
97
-
117
+
98
118
  # Create and return a SurveySession object
99
119
  return SurveySession(
100
120
  id=response_data.id,
101
121
  agent_id=response_data.agent_id,
102
122
  status=response_data.status,
103
- client=self
123
+ client=self,
104
124
  )
105
125
 
106
- async def get_survey_session(self, session_id: Union[str, uuid.UUID]) -> SurveySessionDetailResponse:
126
+ async def get_survey_session_details(
127
+ self, session_id: Union[str, uuid.UUID]
128
+ ) -> SurveySessionDetailResponse:
107
129
  """Retrieves detailed information about a survey session including typed conversation history."""
108
130
  endpoint = f"sessions/{str(session_id)}"
109
131
  response_data = await self._request(
110
- "GET",
111
- endpoint,
112
- response_model=SurveySessionDetailResponse
132
+ "GET", endpoint, response_model=SurveySessionDetailResponse
113
133
  )
114
134
  return response_data
115
135
 
116
- async def create_population(self, name: str, description: Optional[str] = None) -> Population:
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)
141
+
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:
117
155
  """Creates a new population."""
118
156
  payload = CreatePopulationPayload(name=name, description=description)
119
- response_data = await self._request("POST", "populations/create", json=payload.model_dump(mode='json', exclude_none=True), response_model=Population)
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
+ )
120
163
  return response_data
121
164
 
122
165
  async def get_population(self, population_id: Union[str, uuid.UUID]) -> Population:
123
- response_data = await self._request("GET", f"populations/get/{str(population_id)}", response_model=Population)
166
+ response_data = await self._request(
167
+ "GET", f"populations/get/{str(population_id)}", response_model=Population
168
+ )
124
169
  return response_data
125
170
 
126
- async def delete_population(self, population_id: Union[str, uuid.UUID]) -> DeletionResponse:
127
- response_data = await self._request("DELETE", f"populations/delete/{str(population_id)}", response_model=DeletionResponse)
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
+ )
128
179
  return response_data
129
180
 
130
- async def get_agents_in_population(self, population_id: Union[str, uuid.UUID]) -> List[AgentModel]:
181
+ async def get_agents_in_population(
182
+ self, population_id: Union[str, uuid.UUID]
183
+ ) -> List[AgentModel]:
131
184
  """Retrieves all agents belonging to a specific population."""
132
185
  endpoint = f"populations/{str(population_id)}/agents"
133
186
  raw_response = await self._request("GET", endpoint)
134
187
  agents_data_list = raw_response.json()
135
188
  return [AgentModel(**data) for data in agents_data_list]
136
189
 
137
- async def create_agent(self, name: str, population_id: Optional[Union[str, uuid.UUID]] = None, agent_data: Optional[List[Dict[str, Any]]] = None) -> AgentModel:
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:
138
196
  """Creates a new agent, optionally within a population and with initial data items."""
139
197
  pop_id_uuid: Optional[uuid.UUID] = None
140
198
  if population_id:
141
- pop_id_uuid = uuid.UUID(str(population_id)) if not isinstance(population_id, uuid.UUID) else population_id
142
-
143
- payload = CreateAgentPayload(name=name, population_id=pop_id_uuid, agent_data=agent_data)
144
- response_data = await self._request("POST", "agents/create", json=payload.model_dump(mode='json', exclude_none=True), response_model=AgentModel)
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
+ )
145
214
  return response_data
146
215
 
147
216
  async def get_agent(self, agent_id: Union[str, uuid.UUID]) -> AgentModel:
148
- response_data = await self._request("GET", f"agents/get/{str(agent_id)}", response_model=AgentModel)
217
+ response_data = await self._request(
218
+ "GET", f"agents/get/{str(agent_id)}", response_model=AgentModel
219
+ )
149
220
  return response_data
150
221
 
151
222
  async def delete_agent(self, agent_id: Union[str, uuid.UUID]) -> DeletionResponse:
152
- response_data = await self._request("DELETE", f"agents/delete/{str(agent_id)}", response_model=DeletionResponse)
223
+ response_data = await self._request(
224
+ "DELETE", f"agents/delete/{str(agent_id)}", response_model=DeletionResponse
225
+ )
153
226
  return response_data
154
227
 
155
- async def create_data_item(self, agent_id: Union[str, uuid.UUID], data_type: str, content: Any) -> DataItem:
228
+ async def create_data_item(
229
+ self, agent_id: Union[str, uuid.UUID], data_type: str, content: Any
230
+ ) -> DataItem:
156
231
  """Creates a new data item for a specific agent."""
157
232
  payload = CreateDataItemPayload(data_type=data_type, content=content)
158
- response_data = await self._request("POST", f"data_item/create/{str(agent_id)}", json=payload.model_dump(mode='json'), response_model=DataItem)
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
+ )
159
239
  return response_data
160
240
 
161
241
  async def get_data_item(self, data_item_id: Union[str, uuid.UUID]) -> DataItem:
162
- response_data = await self._request("GET", f"data_item/get/{str(data_item_id)}", response_model=DataItem)
242
+ response_data = await self._request(
243
+ "GET", f"data_item/get/{str(data_item_id)}", response_model=DataItem
244
+ )
163
245
  return response_data
164
246
 
165
- async def list_data_items(self, agent_id: Union[str, uuid.UUID], data_type: Optional[str] = None) -> List[DataItem]:
247
+ async def list_data_items(
248
+ self, agent_id: Union[str, uuid.UUID], data_type: Optional[str] = None
249
+ ) -> List[DataItem]:
166
250
  params = {}
167
251
  if data_type:
168
252
  params["data_type"] = data_type
169
253
  agent_id_str = str(agent_id)
170
- raw_response = await self._request("GET", f"data_item/list/{agent_id_str}", params=params)
171
- return [DataItem(**item) for item in raw_response.json()]
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()]
172
258
 
173
- async def update_data_item(self, data_item_id: Union[str, uuid.UUID], content: Any) -> DataItem:
259
+ async def update_data_item(
260
+ self, data_item_id: Union[str, uuid.UUID], content: Any
261
+ ) -> DataItem:
174
262
  """Updates an existing data item."""
175
263
  payload = UpdateDataItemPayload(content=content)
176
- response_data = await self._request("POST", f"data_item/update/{str(data_item_id)}", json=payload.model_dump(), response_model=DataItem)
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
+ )
177
270
  return response_data
178
271
 
179
- async def delete_data_item(self, data_item_id: Union[str, uuid.UUID]) -> DeletionResponse:
180
- response_data = await self._request("DELETE", f"data_item/delete/{str(data_item_id)}", response_model=DeletionResponse)
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
+ )
181
280
  return response_data
182
281
 
183
- async def generate_qual_response(self, agent_id: uuid.UUID, question: str, image_url: Optional[str] = None) -> QualGenerationResponse:
282
+ async def generate_qual_response(
283
+ self, agent_id: uuid.UUID, question: str, image_url: Optional[str] = None
284
+ ) -> QualGenerationResponse:
184
285
  """Generates a qualitative response from an agent based on a question."""
185
286
  endpoint = f"/generation/qual/{str(agent_id)}"
186
287
  request_payload = QualGenerationRequest(question=question, image_url=image_url)
187
288
  response_data = await self._request(
188
- "POST",
189
- endpoint,
190
- json=request_payload.model_dump(),
191
- response_model=QualGenerationResponse
289
+ "POST",
290
+ endpoint,
291
+ json=request_payload.model_dump(),
292
+ response_model=QualGenerationResponse,
192
293
  )
193
294
  return response_data
194
295
 
195
- async def generate_mc_response(self, agent_id: uuid.UUID, question: str, options: List[str], image_url: Optional[str] = None) -> MCGenerationResponse:
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:
196
303
  """Generates a multiple-choice response from an agent."""
197
304
  endpoint = f"generation/mc/{str(agent_id)}"
198
- request_payload = MCGenerationRequest(question=question, options=options, image_url=image_url)
305
+ request_payload = MCGenerationRequest(
306
+ question=question, options=options, image_url=image_url
307
+ )
199
308
  response_data = await self._request(
200
- "POST",
201
- endpoint,
202
- json=request_payload.model_dump(),
203
- response_model=MCGenerationResponse
309
+ "POST",
310
+ endpoint,
311
+ json=request_payload.model_dump(),
312
+ response_model=MCGenerationResponse,
204
313
  )
205
314
  return response_data
206
315
 
207
316
  async def aclose(self):
208
- await self._client.aclose()
317
+ await self._client.aclose()
209
318
 
210
319
  async def __aenter__(self):
211
320
  return self
@@ -9,17 +9,15 @@ from .models import (
9
9
  SurveySessionCloseResponse,
10
10
  AddContextRequest,
11
11
  AddContextResponse,
12
- SurveySessionDetailResponse,
12
+ SurveySessionDetailResponse
13
13
  )
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from .client import Simile
17
17
 
18
-
19
18
  class Agent:
20
19
  """Represents an agent and provides methods for interacting with it directly."""
21
-
22
- def __init__(self, agent_id: uuid.UUID, client: "Simile"):
20
+ def __init__(self, agent_id: uuid.UUID, client: 'Simile'):
23
21
  self._agent_id = agent_id
24
22
  self._client = client
25
23
 
@@ -27,32 +25,18 @@ class Agent:
27
25
  def id(self) -> uuid.UUID:
28
26
  return self._agent_id
29
27
 
30
- async def generate_qual_response(
31
- self, question: str, image_url: Optional[str] = None
32
- ) -> QualGenerationResponse:
28
+ async def generate_qual_response(self, question: str, image_url: Optional[str] = None) -> QualGenerationResponse:
33
29
  """Generates a qualitative response from this agent based on a question."""
34
- return await self._client.generate_qual_response(
35
- agent_id=self._agent_id, question=question, image_url=image_url
36
- )
30
+ return await self._client.generate_qual_response(agent_id=self._agent_id, question=question, image_url=image_url)
37
31
 
38
- async def generate_mc_response(
39
- self, question: str, options: List[str], image_url: Optional[str] = None
40
- ) -> MCGenerationResponse:
32
+ async def generate_mc_response(self, question: str, options: List[str], image_url: Optional[str] = None) -> MCGenerationResponse:
41
33
  """Generates a multiple-choice response from this agent."""
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
- )
34
+ return await self._client.generate_mc_response(agent_id=self._agent_id, question=question, options=options, image_url=image_url)
48
35
 
49
36
 
50
37
  class SurveySession:
51
38
  """Represents an active survey session with an agent, allowing for contextual multi-turn generation."""
52
-
53
- def __init__(
54
- self, id: uuid.UUID, agent_id: uuid.UUID, status: str, client: "Simile"
55
- ):
39
+ def __init__(self, id: uuid.UUID, agent_id: uuid.UUID, status: str, client: 'Simile'):
56
40
  self._id = id
57
41
  self._agent_id = agent_id
58
42
  self._status = status
@@ -74,37 +58,26 @@ class SurveySession:
74
58
  """Retrieves detailed information about this survey session including typed conversation history."""
75
59
  return await self._client.get_survey_session(self._id)
76
60
 
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:
61
+ async def generate_qual_response(self, question: str, image_url: Optional[str] = None, images: Optional[Dict[str, str]] = None) -> QualGenerationResponse:
83
62
  """Generates a qualitative response within this survey session."""
84
63
  endpoint = f"sessions/{str(self._id)}/qual"
85
- payload = QualGenerationRequest(
86
- question=question, image_url=image_url, images=images
87
- )
64
+ payload = QualGenerationRequest(question=question, image_url=image_url, images=images)
88
65
  return await self._client._request(
89
66
  "POST",
90
67
  endpoint,
91
- json=payload.model_dump(),
92
- response_model=QualGenerationResponse,
68
+ json=payload.model_dump(),
69
+ response_model=QualGenerationResponse
93
70
  )
94
71
 
95
- async def generate_mc_response(
96
- self, question: str, options: List[str], image_url: Optional[str] = None
97
- ) -> MCGenerationResponse:
72
+ async def generate_mc_response(self, question: str, options: List[str], image_url: Optional[str] = None) -> MCGenerationResponse:
98
73
  """Generates a multiple-choice response within this survey session."""
99
74
  endpoint = f"sessions/{str(self._id)}/mc"
100
- payload = MCGenerationRequest(
101
- question=question, options=options, image_url=image_url
102
- )
75
+ payload = MCGenerationRequest(question=question, options=options, image_url=image_url)
103
76
  return await self._client._request(
104
77
  "POST",
105
78
  endpoint,
106
- json=payload.model_dump(),
107
- response_model=MCGenerationResponse,
79
+ json=payload.model_dump(),
80
+ response_model=MCGenerationResponse
108
81
  )
109
82
 
110
83
  async def add_context(self, ctx: str) -> AddContextResponse:
@@ -115,12 +88,14 @@ class SurveySession:
115
88
  "POST",
116
89
  endpoint,
117
90
  json=payload.model_dump(),
118
- response_model=AddContextResponse,
91
+ response_model=AddContextResponse
119
92
  )
120
93
 
121
94
  async def close(self) -> SurveySessionCloseResponse:
122
95
  """Closes this survey session on the server."""
123
96
  endpoint = f"sessions/{str(self._id)}/close"
124
97
  return await self._client._request(
125
- "POST", endpoint, response_model=SurveySessionCloseResponse
98
+ "POST",
99
+ endpoint,
100
+ response_model=SurveySessionCloseResponse
126
101
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simile
3
- Version: 0.2.7
3
+ Version: 0.2.8
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes