aisberg 0.1.0__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.
- aisberg/__init__.py +7 -0
- aisberg/abstract/__init__.py +0 -0
- aisberg/abstract/modules.py +57 -0
- aisberg/api/__init__.py +0 -0
- aisberg/api/async_endpoints.py +333 -0
- aisberg/api/endpoints.py +328 -0
- aisberg/async_client.py +107 -0
- aisberg/client.py +108 -0
- aisberg/config.py +17 -0
- aisberg/exceptions.py +22 -0
- aisberg/models/__init__.py +0 -0
- aisberg/models/chat.py +143 -0
- aisberg/models/collections.py +36 -0
- aisberg/models/embeddings.py +92 -0
- aisberg/models/models.py +39 -0
- aisberg/models/requests.py +11 -0
- aisberg/models/token.py +11 -0
- aisberg/models/tools.py +73 -0
- aisberg/models/workflows.py +66 -0
- aisberg/modules/__init__.py +23 -0
- aisberg/modules/chat.py +403 -0
- aisberg/modules/collections.py +117 -0
- aisberg/modules/document.py +117 -0
- aisberg/modules/embeddings.py +309 -0
- aisberg/modules/me.py +77 -0
- aisberg/modules/models.py +108 -0
- aisberg/modules/tools.py +78 -0
- aisberg/modules/workflows.py +140 -0
- aisberg/requests/__init__.py +0 -0
- aisberg/requests/async_requests.py +85 -0
- aisberg/requests/sync_requests.py +85 -0
- aisberg/utils.py +111 -0
- aisberg-0.1.0.dist-info/METADATA +212 -0
- aisberg-0.1.0.dist-info/RECORD +43 -0
- aisberg-0.1.0.dist-info/WHEEL +5 -0
- aisberg-0.1.0.dist-info/licenses/LICENSE +9 -0
- aisberg-0.1.0.dist-info/top_level.txt +3 -0
- tests/integration/test_collections_integration.py +115 -0
- tests/unit/test_collections_sync.py +104 -0
- tmp/test.py +33 -0
- tmp/test_async.py +126 -0
- tmp/test_doc_parse.py +12 -0
- tmp/test_sync.py +146 -0
aisberg/models/chat.py
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
from typing import Union, Sequence, Tuple, Dict, Any, List, Optional, Literal
|
2
|
+
from pydantic import BaseModel, Field
|
3
|
+
from enum import Enum
|
4
|
+
|
5
|
+
|
6
|
+
class RoleEnum(str, Enum):
|
7
|
+
user = "user"
|
8
|
+
assistant = "assistant"
|
9
|
+
system = "system"
|
10
|
+
tool = "tool"
|
11
|
+
|
12
|
+
|
13
|
+
class ToolCall(BaseModel):
|
14
|
+
id: str
|
15
|
+
type: str = "function"
|
16
|
+
function: "FunctionCall"
|
17
|
+
|
18
|
+
|
19
|
+
class FunctionCall(BaseModel):
|
20
|
+
name: str
|
21
|
+
arguments: str # JSON string des arguments
|
22
|
+
|
23
|
+
|
24
|
+
class BaseMessage(BaseModel):
|
25
|
+
role: RoleEnum
|
26
|
+
content: Union[str, None]
|
27
|
+
|
28
|
+
|
29
|
+
class HumanMessage(BaseMessage):
|
30
|
+
role: RoleEnum = Field(default=RoleEnum.user, frozen=True)
|
31
|
+
|
32
|
+
|
33
|
+
class AIMessage(BaseMessage):
|
34
|
+
role: RoleEnum = Field(default=RoleEnum.assistant, frozen=True)
|
35
|
+
tool_calls: Optional[List[ToolCall]] = None
|
36
|
+
|
37
|
+
|
38
|
+
class SystemMessage(BaseMessage):
|
39
|
+
role: RoleEnum = Field(default=RoleEnum.system, frozen=True)
|
40
|
+
|
41
|
+
|
42
|
+
class ToolMessage(BaseMessage):
|
43
|
+
role: RoleEnum = Field(default=RoleEnum.tool, frozen=True)
|
44
|
+
tool_call_id: str # ID du tool_call auquel ce message répond
|
45
|
+
|
46
|
+
|
47
|
+
# Types de représentations acceptées comme "message"
|
48
|
+
MessageLikeRepresentation = Union[
|
49
|
+
BaseMessage, # BaseMessage ou ses sous-classes
|
50
|
+
str, # Simple string message
|
51
|
+
Tuple[str, str], # (role, content)
|
52
|
+
Dict[str, Any], # dict style {"role": "user", "content": "..."}
|
53
|
+
]
|
54
|
+
|
55
|
+
# Entrée possible pour un LLM
|
56
|
+
LanguageModelInput = Union[str, Sequence[MessageLikeRepresentation]]
|
57
|
+
|
58
|
+
|
59
|
+
class ChatMessageContent(BaseModel):
|
60
|
+
role: str
|
61
|
+
content: Optional[str] = ""
|
62
|
+
refusal: Optional[str] = None
|
63
|
+
annotations: Optional[Dict[str, Any]] = None
|
64
|
+
function_call: Optional[FunctionCall] = None
|
65
|
+
tool_calls: Optional[List[ToolCall]] = None
|
66
|
+
reasoning_content: Optional[str] = None
|
67
|
+
|
68
|
+
|
69
|
+
class Delta(BaseModel):
|
70
|
+
content: Optional[str] = ""
|
71
|
+
function_call: Optional[dict] = None
|
72
|
+
tool_calls: Optional[list] = None
|
73
|
+
|
74
|
+
|
75
|
+
class ChatChoice(BaseModel):
|
76
|
+
index: int
|
77
|
+
message: ChatMessageContent
|
78
|
+
finish_reason: Optional[str]
|
79
|
+
|
80
|
+
|
81
|
+
class ChoiceChunk(BaseModel):
|
82
|
+
index: int
|
83
|
+
delta: Delta
|
84
|
+
finish_reason: Optional[str]
|
85
|
+
|
86
|
+
|
87
|
+
class ChatUsage(BaseModel):
|
88
|
+
prompt_tokens: int
|
89
|
+
completion_tokens: int
|
90
|
+
total_tokens: int
|
91
|
+
|
92
|
+
|
93
|
+
class ChatCompletionResponse(BaseModel):
|
94
|
+
id: str
|
95
|
+
object: str
|
96
|
+
created: int
|
97
|
+
model: str
|
98
|
+
choices: List[ChatChoice]
|
99
|
+
usage: Optional[ChatUsage] = None
|
100
|
+
|
101
|
+
|
102
|
+
class ChatCompletionChunk(BaseModel):
|
103
|
+
id: str
|
104
|
+
object: Literal["chat.completion.chunk"]
|
105
|
+
created: int
|
106
|
+
model: str
|
107
|
+
choices: List[ChoiceChunk]
|
108
|
+
usage: Optional[ChatUsage] = None
|
109
|
+
|
110
|
+
|
111
|
+
def parse_message(msg: MessageLikeRepresentation) -> BaseMessage:
|
112
|
+
if isinstance(msg, BaseMessage):
|
113
|
+
return msg
|
114
|
+
elif isinstance(msg, HumanMessage):
|
115
|
+
return msg
|
116
|
+
elif isinstance(msg, AIMessage):
|
117
|
+
return msg
|
118
|
+
elif isinstance(msg, SystemMessage):
|
119
|
+
return msg
|
120
|
+
elif isinstance(msg, ToolMessage):
|
121
|
+
return msg
|
122
|
+
elif isinstance(msg, str):
|
123
|
+
return HumanMessage(content=msg)
|
124
|
+
elif isinstance(msg, tuple) and len(msg) == 2:
|
125
|
+
return BaseMessage(role=RoleEnum(msg[0]), content=msg[1])
|
126
|
+
elif isinstance(msg, dict):
|
127
|
+
return BaseMessage(**msg)
|
128
|
+
else:
|
129
|
+
raise ValueError(f"Invalid message representation: {msg}")
|
130
|
+
|
131
|
+
|
132
|
+
def format_messages(input: LanguageModelInput) -> list[dict]:
|
133
|
+
"""
|
134
|
+
Normalise et formate les messages pour l’API LLM (OpenAI-like).
|
135
|
+
"""
|
136
|
+
if isinstance(input, str):
|
137
|
+
messages = [HumanMessage(content=input)]
|
138
|
+
else:
|
139
|
+
messages = [parse_message(msg) for msg in input]
|
140
|
+
return [
|
141
|
+
msg.model_dump(include={"role", "content", "tool_calls", "tool_call_id"})
|
142
|
+
for msg in messages
|
143
|
+
]
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from typing import List, Optional, Union
|
2
|
+
from pydantic import BaseModel
|
3
|
+
|
4
|
+
|
5
|
+
class Collection(BaseModel):
|
6
|
+
name: str
|
7
|
+
|
8
|
+
|
9
|
+
class GroupCollections(BaseModel):
|
10
|
+
group: str
|
11
|
+
collections: List[Collection]
|
12
|
+
|
13
|
+
|
14
|
+
# Modèle plus structuré pour payload
|
15
|
+
class Payload(BaseModel):
|
16
|
+
method: Optional[str] = None
|
17
|
+
norm: Optional[Union[str, bool]] = None
|
18
|
+
filetype: Optional[str] = None
|
19
|
+
filename: Optional[str] = None
|
20
|
+
dense_encoder: Optional[str] = None
|
21
|
+
Category: Optional[str] = None
|
22
|
+
text: Optional[str] = None
|
23
|
+
timestamp: Optional[str] = None
|
24
|
+
collection_name: Optional[str] = None
|
25
|
+
sparse_encoder: Optional[str] = None
|
26
|
+
|
27
|
+
|
28
|
+
class PointDetails(BaseModel):
|
29
|
+
id: str
|
30
|
+
payload: Payload
|
31
|
+
|
32
|
+
|
33
|
+
class CollectionDetails(BaseModel):
|
34
|
+
name: str
|
35
|
+
group: str
|
36
|
+
points: List[PointDetails]
|
@@ -0,0 +1,92 @@
|
|
1
|
+
from typing import List, Optional, Dict, Any, Literal, Union
|
2
|
+
from pydantic import BaseModel, RootModel, ConfigDict
|
3
|
+
|
4
|
+
|
5
|
+
class EmbeddingItem(BaseModel):
|
6
|
+
embedding: List[float]
|
7
|
+
index: int
|
8
|
+
object: str
|
9
|
+
|
10
|
+
|
11
|
+
class UsageDetails(BaseModel):
|
12
|
+
prompt_tokens: int
|
13
|
+
total_tokens: int
|
14
|
+
completion_tokens: int
|
15
|
+
prompt_tokens_details: Optional[dict] = None
|
16
|
+
|
17
|
+
|
18
|
+
class EncodingResponse(BaseModel):
|
19
|
+
id: str
|
20
|
+
object: str
|
21
|
+
model: str
|
22
|
+
created: int
|
23
|
+
data: List[EmbeddingItem]
|
24
|
+
usage: UsageDetails
|
25
|
+
|
26
|
+
|
27
|
+
class ChunkData(BaseModel):
|
28
|
+
id: str
|
29
|
+
idx: int
|
30
|
+
filename: str
|
31
|
+
text: str
|
32
|
+
collection_name: str
|
33
|
+
filetype: str
|
34
|
+
dense_encoder: str
|
35
|
+
sparse_encoder: str
|
36
|
+
timestamp: str
|
37
|
+
norm: Optional[Union[bool, str]] = None
|
38
|
+
rrf_score: Optional[float] = None
|
39
|
+
chunk_method: Optional[str] = None
|
40
|
+
|
41
|
+
# Pour permettre l'ajout de clés dynamiques pour les métadonnées
|
42
|
+
model_config = ConfigDict(extra="allow")
|
43
|
+
|
44
|
+
def metadata(self) -> Dict[str, Any]:
|
45
|
+
"""Retourne les métadonnées du ChunkData."""
|
46
|
+
fields = set(self.model_fields.keys())
|
47
|
+
return {k: v for k, v in self.model_dump().items() if k not in fields}
|
48
|
+
|
49
|
+
|
50
|
+
class ChunksDataList(RootModel[List[ChunkData]]):
|
51
|
+
def metadata(self) -> List[Dict[str, Any]]:
|
52
|
+
"""Retourne une liste des métadonnées de chaque ChunkData."""
|
53
|
+
return [chunk.metadata() for chunk in self.root]
|
54
|
+
|
55
|
+
def texts(self) -> List[str]:
|
56
|
+
"""Retourne une liste des textes de chaque ChunkData."""
|
57
|
+
return [chunk.text for chunk in self.root]
|
58
|
+
|
59
|
+
def __iter__(self):
|
60
|
+
return iter(self.root)
|
61
|
+
|
62
|
+
def __len__(self):
|
63
|
+
return len(self.root)
|
64
|
+
|
65
|
+
|
66
|
+
class RerankerDocument(BaseModel):
|
67
|
+
text: str
|
68
|
+
|
69
|
+
|
70
|
+
class RerankerResult(BaseModel):
|
71
|
+
index: int
|
72
|
+
document: RerankerDocument
|
73
|
+
relevance_score: float
|
74
|
+
|
75
|
+
|
76
|
+
class RerankerResponse(BaseModel):
|
77
|
+
id: str
|
78
|
+
model: str
|
79
|
+
usage: Dict[str, int]
|
80
|
+
results: List[RerankerResult]
|
81
|
+
|
82
|
+
def filter_by_relevance_score(self, threshold: float) -> "RerankerResponse":
|
83
|
+
"""Retourne une nouvelle instance filtrée de RerankerResponse."""
|
84
|
+
filtered_results = [
|
85
|
+
result for result in self.results if result.relevance_score >= threshold
|
86
|
+
]
|
87
|
+
return RerankerResponse(
|
88
|
+
id=self.id, model=self.model, usage=self.usage, results=filtered_results
|
89
|
+
)
|
90
|
+
|
91
|
+
|
92
|
+
EncodingFormat = Optional[Literal["float", "base64"]]
|
aisberg/models/models.py
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
from typing import Optional, List, Any
|
2
|
+
from pydantic import BaseModel
|
3
|
+
|
4
|
+
|
5
|
+
class ModelPermission(BaseModel):
|
6
|
+
id: Optional[str] = None
|
7
|
+
object: Optional[str] = None
|
8
|
+
created: Optional[int] = None
|
9
|
+
allow_create_engine: Optional[bool] = None
|
10
|
+
allow_sampling: Optional[bool] = None
|
11
|
+
allow_logprobs: Optional[bool] = None
|
12
|
+
allow_search_indices: Optional[bool] = None
|
13
|
+
allow_view: Optional[bool] = None
|
14
|
+
allow_fine_tuning: Optional[bool] = None
|
15
|
+
organization: Optional[str] = None
|
16
|
+
group: Optional[Any] = None
|
17
|
+
is_blocking: Optional[bool] = None
|
18
|
+
|
19
|
+
|
20
|
+
class ModelMeta(BaseModel):
|
21
|
+
vocab_type: Optional[int] = None
|
22
|
+
n_vocab: Optional[int] = None
|
23
|
+
n_ctx_train: Optional[int] = None
|
24
|
+
n_embd: Optional[int] = None
|
25
|
+
n_params: Optional[int] = None
|
26
|
+
size: Optional[int] = None
|
27
|
+
|
28
|
+
|
29
|
+
class Model(BaseModel):
|
30
|
+
id: Optional[str] = None
|
31
|
+
created: Optional[int] = None
|
32
|
+
object: Optional[str] = None
|
33
|
+
owned_by: Optional[str] = None
|
34
|
+
root: Optional[str] = None
|
35
|
+
parent: Optional[Any] = None
|
36
|
+
max_model_len: Optional[int] = None
|
37
|
+
permission: Optional[List[ModelPermission]] = None
|
38
|
+
language: Optional[List[str]] = None
|
39
|
+
meta: Optional[ModelMeta] = None
|
aisberg/models/token.py
ADDED
aisberg/models/tools.py
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
from typing import Dict, List, Iterable
|
2
|
+
from pydantic import BaseModel, Field
|
3
|
+
|
4
|
+
|
5
|
+
class Property(BaseModel):
|
6
|
+
type: str = Field(..., examples=["string"])
|
7
|
+
description: str
|
8
|
+
|
9
|
+
|
10
|
+
class Parameters(BaseModel):
|
11
|
+
"""Schéma JSON Schema standard OpenAI pour les paramètres."""
|
12
|
+
|
13
|
+
type: str = Field(default="object", frozen=True)
|
14
|
+
properties: Dict[str, Property]
|
15
|
+
required: List[str]
|
16
|
+
|
17
|
+
|
18
|
+
class Function(BaseModel):
|
19
|
+
name: str
|
20
|
+
description: str
|
21
|
+
parameters: Parameters
|
22
|
+
|
23
|
+
|
24
|
+
class Tool(BaseModel):
|
25
|
+
type: str = Field(default="function", frozen=True)
|
26
|
+
function: Function
|
27
|
+
|
28
|
+
|
29
|
+
def make_tool(
|
30
|
+
*,
|
31
|
+
name: str,
|
32
|
+
description: str,
|
33
|
+
params: Dict[str, str], # {"param": "description", ...}
|
34
|
+
) -> Tool:
|
35
|
+
"""Crée un objet `Tool` à partir des paramètres fournis.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
name: Nom de la fonction.
|
39
|
+
description: Description de la fonction.
|
40
|
+
params: Dictionnaire des paramètres avec leur description.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
Un objet `Tool` prêt à être utilisé.
|
44
|
+
"""
|
45
|
+
properties = {
|
46
|
+
key: Property(type="string", description=desc) # <-- adapt typage si besoin
|
47
|
+
for key, desc in params.items()
|
48
|
+
}
|
49
|
+
return Tool(
|
50
|
+
function=Function(
|
51
|
+
name=name,
|
52
|
+
description=description,
|
53
|
+
parameters=Parameters(
|
54
|
+
properties=properties,
|
55
|
+
required=list(params.keys()),
|
56
|
+
),
|
57
|
+
)
|
58
|
+
)
|
59
|
+
|
60
|
+
|
61
|
+
def tools_to_payload(tools: Iterable[Tool]) -> List[Dict]:
|
62
|
+
"""
|
63
|
+
Convertit des objets `Tool` (Pydantic) en payload brut..
|
64
|
+
|
65
|
+
Args:
|
66
|
+
tools: Un itérable d'instances `Tool`.
|
67
|
+
Returns:
|
68
|
+
Une liste de dicts sérialisables en JSON.
|
69
|
+
"""
|
70
|
+
if not isinstance(tools, Iterable) or not tools:
|
71
|
+
return []
|
72
|
+
|
73
|
+
return [tool.model_dump(mode="json", exclude_none=True) for tool in tools]
|
@@ -0,0 +1,66 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import Optional, List, Dict, Any
|
3
|
+
from pydantic import BaseModel, ConfigDict
|
4
|
+
|
5
|
+
|
6
|
+
class Workflow(BaseModel):
|
7
|
+
name: str
|
8
|
+
id: str
|
9
|
+
group: str
|
10
|
+
createdAt: datetime
|
11
|
+
updatedAt: datetime
|
12
|
+
description: Optional[str] = None
|
13
|
+
isActive: Optional[bool] = True
|
14
|
+
|
15
|
+
|
16
|
+
class Input(BaseModel):
|
17
|
+
input_id: str
|
18
|
+
input_type: str
|
19
|
+
input_name: str
|
20
|
+
value: Dict[str, Any]
|
21
|
+
linkable: bool
|
22
|
+
|
23
|
+
|
24
|
+
class Output(BaseModel):
|
25
|
+
output_id: str
|
26
|
+
output_type: str
|
27
|
+
output_name: str
|
28
|
+
linkable: bool
|
29
|
+
|
30
|
+
|
31
|
+
class Position(BaseModel):
|
32
|
+
x: float
|
33
|
+
y: float
|
34
|
+
_id: str
|
35
|
+
|
36
|
+
|
37
|
+
class Node(BaseModel):
|
38
|
+
inputs: List[Input]
|
39
|
+
outputs: List[Output]
|
40
|
+
node_id: str
|
41
|
+
name: str
|
42
|
+
source_nodes_id: Optional[List[str]]
|
43
|
+
type: str
|
44
|
+
target_nodes: List[Dict[str, Any]]
|
45
|
+
position: Position
|
46
|
+
_id: str
|
47
|
+
|
48
|
+
|
49
|
+
class WorkflowDetails(BaseModel):
|
50
|
+
id: str
|
51
|
+
group: str
|
52
|
+
name: str
|
53
|
+
createdAt: datetime
|
54
|
+
updatedAt: datetime
|
55
|
+
starting_node_id: str
|
56
|
+
nodes: List[Node]
|
57
|
+
|
58
|
+
|
59
|
+
class WorkflowRunChunk(BaseModel):
|
60
|
+
response: Optional[str] = None
|
61
|
+
model_config = ConfigDict(extra="allow")
|
62
|
+
|
63
|
+
|
64
|
+
class WorkflowRunResult(BaseModel):
|
65
|
+
response: Optional[str] = None
|
66
|
+
model_config = ConfigDict(extra="allow")
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from .chat import AsyncChatModule, SyncChatModule
|
2
|
+
from .collections import AsyncCollectionsModule, SyncCollectionsModule
|
3
|
+
from .embeddings import AsyncEmbeddingsModule, SyncEmbeddingsModule
|
4
|
+
from .me import AsyncMeModule, SyncMeModule
|
5
|
+
from .models import AsyncModelsModule, SyncModelsModule
|
6
|
+
from .workflows import AsyncWorkflowsModule, SyncWorkflowsModule
|
7
|
+
from .tools import ToolsModule
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"AsyncChatModule",
|
11
|
+
"SyncChatModule",
|
12
|
+
"AsyncCollectionsModule",
|
13
|
+
"SyncCollectionsModule",
|
14
|
+
"AsyncEmbeddingsModule",
|
15
|
+
"SyncEmbeddingsModule",
|
16
|
+
"AsyncMeModule",
|
17
|
+
"SyncMeModule",
|
18
|
+
"AsyncModelsModule",
|
19
|
+
"SyncModelsModule",
|
20
|
+
"AsyncWorkflowsModule",
|
21
|
+
"SyncWorkflowsModule",
|
22
|
+
"ToolsModule",
|
23
|
+
]
|