Python: added poe setup and docs (#131)

* added poe setup and docs

* smaller bandit exclude

* updated poe

* updated naming

* added something in samples

* exclude docs from bandit

* updated readme

* removed ds_store

* updated readme
This commit is contained in:
Eduard van Valkenburg
2025-07-07 17:03:57 +02:00
committed by GitHub
Unverified
parent 94c5d59984
commit 91c5414836
59 changed files with 4327 additions and 199 deletions
+12 -2
View File
@@ -92,7 +92,15 @@ def ai_function(
description: str | None = None,
additional_properties: dict[str, Any] | None = None,
) -> AIFunction[Any, ReturnT] | Callable[[Callable[..., ReturnT | Awaitable[ReturnT]]], AIFunction[Any, ReturnT]]:
"""Create a AIFunction from a function and return the callable tool object."""
"""Decorate a function to turn it into a AIFunction that can be passed to models.
Args:
func: The function to wrap. If None, returns a decorator.
name: The name of the tool. Defaults to the function's name.
description: A description of the tool. Defaults to the function's docstring.
additional_properties: Additional properties to set on the tool.
"""
def wrapper(f: Callable[..., ReturnT | Awaitable[ReturnT]]) -> AIFunction[Any, ReturnT]:
tool_name: str = name or getattr(f, "__name__", "unknown_function") # type: ignore[assignment]
@@ -106,7 +114,9 @@ def ai_function(
for pname, param in sig.parameters.items()
if pname not in {"self", "cls"}
}
input_model = create_model(f"{tool_name}_input", **fields) # type: ignore[call-overload]
input_model: Any = create_model(f"{tool_name}_input", **fields) # type: ignore[call-overload]
if not issubclass(input_model, BaseModel):
raise TypeError(f"Input model for {tool_name} must be a subclass of BaseModel, got {input_model}")
return functools.update_wrapper( # type: ignore[return-value]
AIFunction[Any, ReturnT](
+67 -68
View File
@@ -71,7 +71,7 @@ class UsageDetails(AFBaseModel):
model_config = ConfigDict(
populate_by_name=True, arbitrary_types_allowed=True, validate_assignment=True, extra="allow"
)
__pydantic_extra__: dict[str, int]
__pydantic_extra__: dict[str, int] # type: ignore[reportIncompatibleVariableOverride]
"""Overriding the default extras type, to make sure all extras are integers."""
input_token_count: int | None = None
@@ -81,6 +81,29 @@ class UsageDetails(AFBaseModel):
total_token_count: int | None = None
"""The total number of tokens used to produce the response."""
def __init__(
self,
input_token_count: int | None = None,
output_token_count: int | None = None,
total_token_count: int | None = None,
**kwargs: int,
) -> None:
"""Initializes the UsageDetails instance.
Args:
input_token_count: The number of tokens in the input.
output_token_count: The number of tokens in the output.
total_token_count: The total number of tokens used to produce the response.
**kwargs: Additional token counts, can be set by passing keyword arguments.
They can be retrieved through the `additional_counts` property.
"""
super().__init__(
input_token_count=input_token_count, # type: ignore[reportCallIssue]
output_token_count=output_token_count, # type: ignore[reportCallIssue]
total_token_count=total_token_count, # type: ignore[reportCallIssue]
**kwargs,
)
@property
def additional_counts(self) -> dict[str, int]:
"""Represents well-known additional counts for usage. This is not an exhaustive list.
@@ -112,29 +135,6 @@ class UsageDetails(AFBaseModel):
**additional_counts,
)
def __init__(
self,
input_token_count: int | None = None,
output_token_count: int | None = None,
total_token_count: int | None = None,
**kwargs: int,
) -> None:
"""Initializes the UsageDetails instance.
Args:
input_token_count: The number of tokens in the input.
output_token_count: The number of tokens in the output.
total_token_count: The total number of tokens used to produce the response.
**kwargs: Additional token counts, can be set by passing keyword arguments.
They can be retrieved through the `additional_counts` property.
"""
super().__init__(
input_token_count=input_token_count,
output_token_count=output_token_count,
total_token_count=total_token_count,
**kwargs,
)
def _process_update(response: "ChatResponse", update: "ChatResponseUpdate") -> None:
"""Processes a single update and modifies the response in place."""
@@ -185,7 +185,7 @@ def _coalesce_text_content(
if not contents:
return
coalesced_contents: list["AIContents"] = []
current_texts = []
current_texts: list[str] = []
first_new_content = None
for i, content in enumerate(contents):
if isinstance(content, type_):
@@ -267,7 +267,7 @@ class TextContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
text=text,
text=text, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -309,7 +309,7 @@ class TextReasoningContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
text=text,
text=text, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -410,7 +410,7 @@ class DataContent(AIContent):
raise ValueError("Either 'data' and 'media_type' or 'uri' must be provided.")
uri = f"data:{media_type};base64,{base64.b64encode(data).decode('utf-8')}"
super().__init__(
uri=uri,
uri=uri, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -477,8 +477,8 @@ class UriContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
uri=uri,
media_type=media_type,
uri=uri, # type: ignore[reportCallIssue]
media_type=media_type, # type: ignore[reportCallIssue]
additional_properties=additional_properties,
raw_representation=raw_representation,
**kwargs,
@@ -532,9 +532,9 @@ class ErrorContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
message=message,
error_code=error_code,
details=details,
message=message, # type: ignore[reportCallIssue]
error_code=error_code, # type: ignore[reportCallIssue]
details=details, # type: ignore[reportCallIssue]
additional_properties=additional_properties,
raw_representation=raw_representation,
**kwargs,
@@ -592,10 +592,10 @@ class FunctionCallContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
call_id=call_id,
name=name,
arguments=arguments,
exception=exception,
call_id=call_id, # type: ignore[reportCallIssue]
name=name, # type: ignore[reportCallIssue]
arguments=arguments, # type: ignore[reportCallIssue]
exception=exception, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -644,9 +644,9 @@ class FunctionResultContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
call_id=call_id,
result=result,
exception=exception,
call_id=call_id, # type: ignore[reportCallIssue]
result=result, # type: ignore[reportCallIssue]
exception=exception, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -685,8 +685,7 @@ class UsageContent(AIContent):
**kwargs: Any additional keyword arguments.
"""
super().__init__(
type=self.type,
details=details,
details=details, # type: ignore[reportCallIssue]
raw_representation=raw_representation,
additional_properties=additional_properties,
**kwargs,
@@ -885,12 +884,12 @@ class ChatMessage(AFBaseModel):
if isinstance(role, str):
role = ChatRole(value=role)
super().__init__(
role=role,
contents=contents,
author_name=author_name,
message_id=message_id,
additional_properties=additional_properties,
raw_representation=raw_representation,
role=role, # type: ignore[reportCallIssue]
contents=contents, # type: ignore[reportCallIssue]
author_name=author_name, # type: ignore[reportCallIssue]
message_id=message_id, # type: ignore[reportCallIssue]
additional_properties=additional_properties, # type: ignore[reportCallIssue]
raw_representation=raw_representation, # type: ignore[reportCallIssue]
)
@@ -1022,15 +1021,15 @@ class ChatResponse(AFBaseModel):
messages.append(ChatMessage(role=ChatRole.ASSISTANT, contents=[text]))
super().__init__(
messages=messages,
response_id=response_id,
conversation_id=conversation_id,
ai_model_id=model_id,
created_at=created_at,
finish_reason=finish_reason,
usage_details=usage_details,
additional_properties=additional_properties,
raw_representation=raw_representation,
messages=messages, # type: ignore[reportCallIssue]
response_id=response_id, # type: ignore[reportCallIssue]
conversation_id=conversation_id, # type: ignore[reportCallIssue]
ai_model_id=model_id, # type: ignore[reportCallIssue]
created_at=created_at, # type: ignore[reportCallIssue]
finish_reason=finish_reason, # type: ignore[reportCallIssue]
usage_details=usage_details, # type: ignore[reportCallIssue]
additional_properties=additional_properties, # type: ignore[reportCallIssue]
raw_representation=raw_representation, # type: ignore[reportCallIssue]
**kwargs,
)
@@ -1260,17 +1259,17 @@ class ChatResponseUpdate(AFBaseModel):
contents.append(text)
super().__init__(
contents=contents,
additional_properties=additional_properties,
author_name=author_name,
conversation_id=conversation_id,
created_at=created_at,
finish_reason=finish_reason,
message_id=message_id,
ai_model_id=ai_model_id,
raw_representation=raw_representation,
response_id=response_id,
role=role,
contents=contents, # type: ignore[reportCallIssue]
additional_properties=additional_properties, # type: ignore[reportCallIssue]
author_name=author_name, # type: ignore[reportCallIssue]
conversation_id=conversation_id, # type: ignore[reportCallIssue]
created_at=created_at, # type: ignore[reportCallIssue]
finish_reason=finish_reason, # type: ignore[reportCallIssue]
message_id=message_id, # type: ignore[reportCallIssue]
ai_model_id=ai_model_id, # type: ignore[reportCallIssue]
raw_representation=raw_representation, # type: ignore[reportCallIssue]
response_id=response_id, # type: ignore[reportCallIssue]
role=role, # type: ignore[reportCallIssue]
)
@property