davidkhala.ai 0.2.1__py3-none-any.whl → 0.2.2__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.
- davidkhala/ai/agent/dify/api/__init__.py +2 -2
- davidkhala/ai/agent/dify/api/app.py +10 -6
- davidkhala/ai/agent/dify/api/knowledge/__init__.py +0 -0
- davidkhala/ai/agent/dify/api/knowledge/chunk.py +14 -0
- davidkhala/ai/agent/dify/api/knowledge/dataset.py +82 -0
- davidkhala/ai/agent/dify/api/knowledge/document.py +42 -0
- davidkhala/ai/agent/dify/api/knowledge/model.py +139 -0
- davidkhala/ai/agent/dify/{ops/console → console}/__init__.py +7 -1
- davidkhala/ai/agent/dify/console/knowledge/__init__.py +0 -0
- davidkhala/ai/agent/dify/console/knowledge/dataset.py +61 -0
- davidkhala/ai/agent/dify/console/knowledge/pipeline.py +127 -0
- davidkhala/ai/agent/dify/{ops/console → console}/plugin.py +20 -6
- davidkhala/ai/agent/dify/console/session.py +50 -0
- davidkhala/ai/agent/dify/db/orm.py +65 -0
- davidkhala/ai/agent/dify/model/__init__.py +7 -0
- davidkhala/ai/agent/dify/{model.py → model/knowledge.py} +1 -12
- davidkhala/ai/agent/dify/{ops/db/orm.py → model/workflow.py} +24 -62
- davidkhala/ai/agent/langgraph.py +1 -1
- davidkhala/ai/ali/dashscope.py +15 -14
- davidkhala/ai/anthropic/__init__.py +6 -0
- davidkhala/ai/api/__init__.py +6 -19
- davidkhala/ai/api/openrouter.py +14 -10
- davidkhala/ai/api/siliconflow.py +2 -4
- davidkhala/ai/atlas/__init__.py +24 -0
- davidkhala/ai/mistral/__init__.py +2 -20
- davidkhala/ai/mistral/agent.py +50 -0
- davidkhala/ai/mistral/ai.py +40 -0
- davidkhala/ai/mistral/file.py +38 -0
- davidkhala/ai/mistral/ocr.py +46 -0
- davidkhala/ai/model/__init__.py +11 -27
- davidkhala/ai/model/chat.py +60 -4
- davidkhala/ai/model/embed.py +8 -0
- davidkhala/ai/model/garden.py +9 -0
- davidkhala/ai/openai/__init__.py +9 -33
- davidkhala/ai/openai/azure.py +51 -0
- davidkhala/ai/openai/native.py +2 -3
- davidkhala/ai/openrouter/__init__.py +24 -13
- {davidkhala_ai-0.2.1.dist-info → davidkhala_ai-0.2.2.dist-info}/METADATA +8 -6
- davidkhala_ai-0.2.2.dist-info/RECORD +65 -0
- davidkhala/ai/agent/dify/api/knowledge.py +0 -191
- davidkhala/ai/agent/dify/ops/__init__.py +0 -1
- davidkhala/ai/agent/dify/ops/console/knowledge.py +0 -158
- davidkhala/ai/agent/dify/ops/console/session.py +0 -32
- davidkhala/ai/huggingface/BAAI.py +0 -10
- davidkhala/ai/huggingface/__init__.py +0 -21
- davidkhala/ai/huggingface/inference.py +0 -13
- davidkhala_ai-0.2.1.dist-info/RECORD +0 -53
- /davidkhala/ai/agent/dify/{ops/db → db}/__init__.py +0 -0
- /davidkhala/ai/agent/dify/{ops/db → db}/app.py +0 -0
- /davidkhala/ai/agent/dify/{ops/db → db}/knowledge.py +0 -0
- /davidkhala/ai/agent/dify/{ops/db → db}/sys.py +0 -0
- {davidkhala_ai-0.2.1.dist-info → davidkhala_ai-0.2.2.dist-info}/WHEEL +0 -0
davidkhala/ai/model/chat.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from typing import Protocol, Any
|
|
1
|
+
from typing import Protocol, Any, Iterable, TypedDict
|
|
2
|
+
|
|
3
|
+
from davidkhala.ai.model import ModelAware
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
class MessageProtocol(Protocol):
|
|
@@ -13,7 +15,61 @@ class ChoicesAware(Protocol):
|
|
|
13
15
|
choices: list[ChoiceProtocol]
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
class ImagePromptDict(TypedDict):
|
|
19
|
+
text: str
|
|
20
|
+
image_url: list[str]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def on_response(response: ChoicesAware, n: int | None):
|
|
17
24
|
contents = [choice.message.content for choice in response.choices]
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
if n:
|
|
26
|
+
assert len(contents) == n, f"expected {n} choices, but got {len(contents)}"
|
|
27
|
+
return contents
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MessageDict(TypedDict):
|
|
31
|
+
content: str | list | None
|
|
32
|
+
role: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def messages_from(*user_prompt: str | ImagePromptDict) -> Iterable[MessageDict]:
|
|
36
|
+
for _ in user_prompt:
|
|
37
|
+
message = MessageDict(role='user', content=None)
|
|
38
|
+
if type(_) == str:
|
|
39
|
+
message['content'] = _
|
|
40
|
+
elif type(_) == dict:
|
|
41
|
+
message['content'] = [{"type": "text", "text": _['text']}]
|
|
42
|
+
message['content'].extend({"type": "image_url", "image_url": {"url": i}} for i in _['image_url'])
|
|
43
|
+
yield message
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ChatAware(ModelAware):
|
|
47
|
+
def __init__(self):
|
|
48
|
+
super().__init__()
|
|
49
|
+
self.messages: list[Any | MessageDict] = []
|
|
50
|
+
self.n: int = 1
|
|
51
|
+
|
|
52
|
+
def as_chat(self, model: str | None, sys_prompt: str = None):
|
|
53
|
+
self.model = model
|
|
54
|
+
if sys_prompt is not None:
|
|
55
|
+
self.messages = [MessageDict(role='system', content=sys_prompt)]
|
|
56
|
+
|
|
57
|
+
def chat(self, *user_prompt, **kwargs): ...
|
|
58
|
+
|
|
59
|
+
def messages_from(self, *user_prompt) -> list[MessageDict]:
|
|
60
|
+
messages = list(self.messages)
|
|
61
|
+
messages.extend(messages_from(*user_prompt))
|
|
62
|
+
return messages
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class CompareChatAware(ChatAware):
|
|
66
|
+
def __init__(self):
|
|
67
|
+
super().__init__()
|
|
68
|
+
self._models = None
|
|
69
|
+
|
|
70
|
+
def as_chat(self, *models: str, sys_prompt: str = None):
|
|
71
|
+
if len(models) > 1:
|
|
72
|
+
self._models = models
|
|
73
|
+
super().as_chat(None, sys_prompt)
|
|
74
|
+
elif len(models) == 1:
|
|
75
|
+
super().as_chat(models[0], sys_prompt)
|
davidkhala/ai/openai/__init__.py
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
|
|
3
|
-
from httpx import URL
|
|
4
3
|
from openai import OpenAI
|
|
5
4
|
|
|
6
|
-
from davidkhala.ai.model import
|
|
7
|
-
from davidkhala.ai.model.
|
|
5
|
+
from davidkhala.ai.model import SDKProtocol, Connectable
|
|
6
|
+
from davidkhala.ai.model.embed import EmbeddingAware
|
|
7
|
+
from davidkhala.ai.model.chat import on_response, ChatAware
|
|
8
|
+
from davidkhala.ai.model.garden import GardenAlike
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
class Client(
|
|
11
|
+
class Client(ChatAware, EmbeddingAware, SDKProtocol, GardenAlike, Connectable):
|
|
11
12
|
def __init__(self, client: OpenAI):
|
|
12
13
|
super().__init__()
|
|
13
|
-
self.client:OpenAI = client
|
|
14
|
-
self.
|
|
15
|
-
|
|
16
|
-
self.encoding_format:Literal["float", "base64"] = "float"
|
|
17
|
-
self.n:int = 1
|
|
14
|
+
self.client: OpenAI = client
|
|
15
|
+
self.encoding_format: Literal["float", "base64"] = "float"
|
|
16
|
+
|
|
18
17
|
def connect(self):
|
|
19
18
|
try:
|
|
20
19
|
type(self).models.fget(self)
|
|
@@ -36,29 +35,9 @@ class Client(AbstractClient):
|
|
|
36
35
|
|
|
37
36
|
def chat(self, *user_prompt, **kwargs):
|
|
38
37
|
|
|
39
|
-
messages = [
|
|
40
|
-
*self.messages,
|
|
41
|
-
]
|
|
42
|
-
for prompt in user_prompt:
|
|
43
|
-
message = {
|
|
44
|
-
"role": "user"
|
|
45
|
-
}
|
|
46
|
-
if type(prompt) == str:
|
|
47
|
-
message['content'] = prompt
|
|
48
|
-
elif type(prompt) == dict:
|
|
49
|
-
message['content'] = [
|
|
50
|
-
{"type": "text", "text": prompt['text']},
|
|
51
|
-
{
|
|
52
|
-
"type": "image_url",
|
|
53
|
-
"image_url": {
|
|
54
|
-
"url": prompt['image_url'],
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
]
|
|
58
|
-
messages.append(message)
|
|
59
38
|
response = self.client.chat.completions.create(
|
|
60
39
|
model=self.model,
|
|
61
|
-
messages=
|
|
40
|
+
messages=self.messages_from(*user_prompt),
|
|
62
41
|
n=self.n,
|
|
63
42
|
**kwargs
|
|
64
43
|
)
|
|
@@ -67,6 +46,3 @@ class Client(AbstractClient):
|
|
|
67
46
|
|
|
68
47
|
def close(self):
|
|
69
48
|
self.client.close()
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
davidkhala/ai/openai/azure.py
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from davidkhala.ml.ocr.interface import FieldProperties
|
|
1
6
|
from davidkhala.utils.syntax.compat import deprecated
|
|
2
7
|
from openai import AzureOpenAI, OpenAI
|
|
8
|
+
from openai.types.chat import (
|
|
9
|
+
ChatCompletionUserMessageParam, ChatCompletionContentPartTextParam, ChatCompletionContentPartImageParam
|
|
10
|
+
)
|
|
11
|
+
from openai.types.chat.chat_completion_content_part_image_param import ImageURL
|
|
12
|
+
from openai.types.shared_params import ResponseFormatJSONSchema
|
|
13
|
+
from openai.types.shared_params.response_format_json_schema import JSONSchema
|
|
3
14
|
|
|
15
|
+
from davidkhala.ai.model.chat import on_response
|
|
4
16
|
from davidkhala.ai.openai import Client
|
|
5
17
|
|
|
6
18
|
|
|
@@ -19,6 +31,45 @@ class ModelDeploymentClient(AzureHosted):
|
|
|
19
31
|
api_key=key,
|
|
20
32
|
))
|
|
21
33
|
|
|
34
|
+
def process(self, file: Path, schema: dict[str, FieldProperties])-> list[dict]:
|
|
35
|
+
with open(file, "rb") as f:
|
|
36
|
+
content = base64.b64encode(f.read()).decode("utf-8")
|
|
37
|
+
required = [k for k, _ in schema.items() if _.required]
|
|
38
|
+
properties = {k: {'type': v.type} for k, v in schema.items()}
|
|
39
|
+
|
|
40
|
+
json_schema = JSONSchema(
|
|
41
|
+
name='-',
|
|
42
|
+
schema={"type": "object",
|
|
43
|
+
"properties": properties,
|
|
44
|
+
"required": required,
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
self.messages.append(ChatCompletionUserMessageParam(
|
|
49
|
+
role='user',
|
|
50
|
+
content=[
|
|
51
|
+
ChatCompletionContentPartTextParam(
|
|
52
|
+
type='text',
|
|
53
|
+
text="Extract the required fields from this image and return the output strictly following the provided JSON schema."),
|
|
54
|
+
ChatCompletionContentPartImageParam(
|
|
55
|
+
type="image_url",
|
|
56
|
+
image_url=ImageURL(
|
|
57
|
+
url=f"data:image/jpeg;base64,{content}",
|
|
58
|
+
detail='auto'
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
))
|
|
63
|
+
response = self.client.chat.completions.create(
|
|
64
|
+
model=self.model,
|
|
65
|
+
messages=self.messages,
|
|
66
|
+
response_format=ResponseFormatJSONSchema(
|
|
67
|
+
type='json_schema',
|
|
68
|
+
json_schema=json_schema
|
|
69
|
+
),
|
|
70
|
+
n=self.n,
|
|
71
|
+
)
|
|
72
|
+
return [json.loads(_) for _ in on_response(response, self.n)]
|
|
22
73
|
|
|
23
74
|
@deprecated("Azure Open AI is deprecated. Please migrate to Microsoft Foundry")
|
|
24
75
|
class OpenAIClient(AzureHosted):
|
davidkhala/ai/openai/native.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Literal
|
|
2
2
|
|
|
3
3
|
from openai import OpenAI
|
|
4
4
|
|
|
@@ -12,8 +12,7 @@ class NativeClient(Client):
|
|
|
12
12
|
base_url=base_url
|
|
13
13
|
))
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
def chat(self, *user_prompt, web_search:Optional[Literal["low", "medium", "high"]]=None, **kwargs):
|
|
15
|
+
def chat(self, *user_prompt, web_search: Literal["low", "medium", "high"] = None, **kwargs):
|
|
17
16
|
opts = {
|
|
18
17
|
**kwargs
|
|
19
18
|
}
|
|
@@ -1,36 +1,47 @@
|
|
|
1
|
+
from openrouter import OpenRouter
|
|
2
|
+
from openrouter.components import Model
|
|
1
3
|
from openrouter.errors import UnauthorizedResponseError
|
|
4
|
+
from openrouter.operations import ListData
|
|
2
5
|
|
|
3
|
-
from davidkhala.ai.model import
|
|
4
|
-
from
|
|
6
|
+
from davidkhala.ai.model import Connectable, SDKProtocol
|
|
7
|
+
from davidkhala.ai.model.chat import CompareChatAware, on_response
|
|
8
|
+
from davidkhala.ai.model.garden import GardenAlike
|
|
5
9
|
|
|
6
10
|
|
|
7
|
-
class Client(
|
|
11
|
+
class Client(CompareChatAware, Connectable, SDKProtocol, GardenAlike):
|
|
8
12
|
def __init__(self, api_key: str):
|
|
9
13
|
super().__init__()
|
|
10
|
-
self.
|
|
11
|
-
self.client = OpenRouter(api_key)
|
|
14
|
+
self.client: OpenRouter = OpenRouter(api_key)
|
|
12
15
|
|
|
13
16
|
def chat(self, *user_prompt, **kwargs):
|
|
14
17
|
r = self.client.chat.send(
|
|
15
18
|
model=self.model,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
]
|
|
19
|
+
models=self._models,
|
|
20
|
+
messages=self.messages_from(*user_prompt)
|
|
21
|
+
# openrouter has no n
|
|
20
22
|
)
|
|
21
|
-
return
|
|
23
|
+
return on_response(r, None)
|
|
24
|
+
|
|
22
25
|
def connect(self):
|
|
23
26
|
try:
|
|
24
|
-
self.
|
|
27
|
+
_ = self.models
|
|
25
28
|
return True
|
|
26
29
|
except UnauthorizedResponseError:
|
|
27
30
|
return False
|
|
28
31
|
|
|
32
|
+
def list_models(self) -> list[Model]:
|
|
33
|
+
return self.client.models.list().data
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def models(self) -> list[str]:
|
|
37
|
+
return [m.id for m in self.list_models()]
|
|
38
|
+
|
|
29
39
|
|
|
30
40
|
class Admin:
|
|
31
41
|
def __init__(self, provisioning_key: str):
|
|
32
42
|
self.provisioning_key = provisioning_key
|
|
33
43
|
self.client = OpenRouter(provisioning_key)
|
|
44
|
+
|
|
34
45
|
@property
|
|
35
|
-
def keys(self):
|
|
36
|
-
return self.client.api_keys.list().data
|
|
46
|
+
def keys(self) -> list[ListData]:
|
|
47
|
+
return self.client.api_keys.list().data
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: davidkhala.ai
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: misc AI modules
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Provides-Extra: ali
|
|
@@ -9,7 +9,10 @@ Requires-Dist: davidkhala-utils; extra == 'ali'
|
|
|
9
9
|
Requires-Dist: wuying-agentbay-sdk; extra == 'ali'
|
|
10
10
|
Provides-Extra: api
|
|
11
11
|
Requires-Dist: davidkhala-utils[http-request]; extra == 'api'
|
|
12
|
+
Provides-Extra: atlas
|
|
13
|
+
Requires-Dist: voyageai; extra == 'atlas'
|
|
12
14
|
Provides-Extra: azure
|
|
15
|
+
Requires-Dist: davidkhala-ml-ocr; extra == 'azure'
|
|
13
16
|
Requires-Dist: davidkhala-utils; extra == 'azure'
|
|
14
17
|
Requires-Dist: openai; extra == 'azure'
|
|
15
18
|
Provides-Extra: dify
|
|
@@ -19,16 +22,15 @@ Requires-Dist: dify-plugin; extra == 'dify'
|
|
|
19
22
|
Provides-Extra: google
|
|
20
23
|
Requires-Dist: google-adk; extra == 'google'
|
|
21
24
|
Requires-Dist: google-genai; extra == 'google'
|
|
22
|
-
Provides-Extra: hf
|
|
23
|
-
Requires-Dist: hf-xet; extra == 'hf'
|
|
24
|
-
Requires-Dist: huggingface-hub; extra == 'hf'
|
|
25
|
-
Requires-Dist: onnx; extra == 'hf'
|
|
26
|
-
Requires-Dist: onnxruntime; extra == 'hf'
|
|
27
25
|
Provides-Extra: langchain
|
|
28
26
|
Requires-Dist: langchain; extra == 'langchain'
|
|
29
27
|
Requires-Dist: langchain-openai; (python_version < '3.14') and extra == 'langchain'
|
|
30
28
|
Requires-Dist: langgraph; extra == 'langchain'
|
|
29
|
+
Provides-Extra: minimax
|
|
30
|
+
Requires-Dist: anthropic; extra == 'minimax'
|
|
31
|
+
Requires-Dist: openai; extra == 'minimax'
|
|
31
32
|
Provides-Extra: mistral
|
|
33
|
+
Requires-Dist: davidkhala-ml-ocr; extra == 'mistral'
|
|
32
34
|
Requires-Dist: mistralai; extra == 'mistral'
|
|
33
35
|
Provides-Extra: openrouter
|
|
34
36
|
Requires-Dist: openrouter; extra == 'openrouter'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
davidkhala/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
davidkhala/ai/opik.py,sha256=YU1XuweMUAzUkhpjxhltt-SBBDBkR3z-PCNo0DqzBRs,39
|
|
3
|
+
davidkhala/ai/you.py,sha256=fmMfJQZcG0e6sKfVQy2jOKZ-jkO-3H6GOGP2U19l4zQ,1759
|
|
4
|
+
davidkhala/ai/agent/README.md,sha256=kIPsx3gOjrpOw7w2qhNEALuCEQkuh4nYp6uBnijdvHE,178
|
|
5
|
+
davidkhala/ai/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
davidkhala/ai/agent/langgraph.py,sha256=vaiHpnYmkjfXiGq-VH0sUn-NXBacnbFW-6E6sUgdNLU,1050
|
|
7
|
+
davidkhala/ai/agent/ragflow.py,sha256=UaK31us6V0NhAPCthGo07rQsm72vlR-McmihC_NDe1g,273
|
|
8
|
+
davidkhala/ai/agent/dify/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
davidkhala/ai/agent/dify/const.py,sha256=gU4lPBe4U2taakN2jhdPMRWXkqlyCg-YRE8JJmtsblo,218
|
|
10
|
+
davidkhala/ai/agent/dify/interface.py,sha256=bTOI38ZjtkgoSw-ysgFwBZ1QkKVAa92gjOnERDoagQA,118
|
|
11
|
+
davidkhala/ai/agent/dify/api/__init__.py,sha256=OevdexhW4rh40uGpzSxmeeff4pslKvygKpxjUQzMc-Y,861
|
|
12
|
+
davidkhala/ai/agent/dify/api/app.py,sha256=XMLwNSpL5BhNZHKx4BEuk9NplIHCToMKXFssrn_7Hu4,3931
|
|
13
|
+
davidkhala/ai/agent/dify/api/knowledge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
davidkhala/ai/agent/dify/api/knowledge/chunk.py,sha256=AurKJCZQQ2RkitLxMRcRPRKOE2WsTm7JSb6AnjJEgEw,470
|
|
15
|
+
davidkhala/ai/agent/dify/api/knowledge/dataset.py,sha256=JO0Au4TTZIzSagkDI1lOULB5SM-WWGnIiQ7HmcZardM,2981
|
|
16
|
+
davidkhala/ai/agent/dify/api/knowledge/document.py,sha256=sjgzwLWar2CsqO8gF93qeRfzw3fNCLgC4PGxD7QhAhE,1261
|
|
17
|
+
davidkhala/ai/agent/dify/api/knowledge/model.py,sha256=fRv4qMsgPMbNU3Q9c03rU4JedoktQ38IjUDrAjQy-8w,3775
|
|
18
|
+
davidkhala/ai/agent/dify/console/__init__.py,sha256=WKXcjjtnWyljhlgrReSneeD87K6GmgGoCmwKCPdGPdc,380
|
|
19
|
+
davidkhala/ai/agent/dify/console/plugin.py,sha256=qwojlnYaIIRqjV8unN1mkMdOT5scG7ZhuVW8Rz8GgVM,2870
|
|
20
|
+
davidkhala/ai/agent/dify/console/session.py,sha256=agS6i7qe-ZGMOawNTh23_bY2ovm0JtGMDLwEuBuRzyk,1604
|
|
21
|
+
davidkhala/ai/agent/dify/console/knowledge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
davidkhala/ai/agent/dify/console/knowledge/dataset.py,sha256=QgHPJSPQmiosc7WI6zLPBXaWLIEOHHOEZlVWNlPljuc,2474
|
|
23
|
+
davidkhala/ai/agent/dify/console/knowledge/pipeline.py,sha256=yg4pYx3PHKFl88_deexv6GgACyUcmnJXgvB91wXyfO4,4353
|
|
24
|
+
davidkhala/ai/agent/dify/db/__init__.py,sha256=HYfJEnoFAoJJck2xvTDYx8zpw9Qao7sHXOGvW0diPqw,517
|
|
25
|
+
davidkhala/ai/agent/dify/db/app.py,sha256=IRiSiR0v387p4p3J7M9xEkJ7pfQyO5DL6chpx7Z2IzA,1319
|
|
26
|
+
davidkhala/ai/agent/dify/db/knowledge.py,sha256=GVaK5QmU_VxB8fDxV60uiYiIeR3JEn3IXJTlJHLiT5U,2917
|
|
27
|
+
davidkhala/ai/agent/dify/db/orm.py,sha256=AJ2tVS18g-uyIPJGdEVIPAtoPYUm3KqzSl7av0S8uzA,2188
|
|
28
|
+
davidkhala/ai/agent/dify/db/sys.py,sha256=U_qqopUMlgsilhHaG_ids6gtd-pNiR_Jm0kAr9hIL7M,188
|
|
29
|
+
davidkhala/ai/agent/dify/model/__init__.py,sha256=VXKaNpQFK8J-j9zp5caOgiQxaQCIoUJjWn6NAjTTok0,104
|
|
30
|
+
davidkhala/ai/agent/dify/model/knowledge.py,sha256=e4CbI3tjIn0gsh4t4ZOMp-JQtWFB7yzWvkioSztWJx0,397
|
|
31
|
+
davidkhala/ai/agent/dify/model/workflow.py,sha256=I7_INuD5QAFT_xERmOwAMOKZEccGZ5COnvivv5fNisA,3044
|
|
32
|
+
davidkhala/ai/agent/dify/plugins/__init__.py,sha256=iTWvutlkN9bXgptesi05M447nTeF5hKFAIfn4EviFj0,183
|
|
33
|
+
davidkhala/ai/agent/dify/plugins/file.py,sha256=o-HjHSFwRTNIYs8IxqZUSnBbh-xr8f-xMUM3iU9wCCQ,390
|
|
34
|
+
davidkhala/ai/agent/dify/plugins/firecrawl.py,sha256=lB_f8W_bdg-7PeBKmF0-HdwYyakV_0D3nET5iT-Z1KM,460
|
|
35
|
+
davidkhala/ai/agent/dify/plugins/jina.py,sha256=dQ5iJxDLWtChXb1IjCtsHctgUtgjOiDfWOuR2u0aUIM,190
|
|
36
|
+
davidkhala/ai/agent/dify/plugins/popular.py,sha256=XMuxqRcIko4gCQORg5HCcwCrbgLcaoRZxCYBIgtkrOo,812
|
|
37
|
+
davidkhala/ai/ali/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
davidkhala/ai/ali/agentbay.py,sha256=O5t71GGwtDgBE1zUXJDYe5djMVwSaNOwn5k8zg1xa18,1200
|
|
39
|
+
davidkhala/ai/ali/dashscope.py,sha256=4KWxl8s6PrKtjgszYM6OIv6r5736EXC1HwLcfJo-x-8,2091
|
|
40
|
+
davidkhala/ai/anthropic/__init__.py,sha256=zzELo9KUD9wKKzrEPYmt-wBHPIvInHzgU2ClfbdgzYo,112
|
|
41
|
+
davidkhala/ai/api/__init__.py,sha256=FTsOpTnG5FxM80mFUYir2THfKmVQEGYnsoO_Egdypzo,1137
|
|
42
|
+
davidkhala/ai/api/openrouter.py,sha256=BBM0HsBwo29PChI4ca8tNiEbzE16-WWc95TqW6k-xn8,2527
|
|
43
|
+
davidkhala/ai/api/siliconflow.py,sha256=hxaEIQc2xi394SS8VdCXu2TWPxjpgc3hATzB03LsZQ0,2073
|
|
44
|
+
davidkhala/ai/atlas/__init__.py,sha256=hNjmpp9fk-GGXVZOjrvs_x4j0b_Wlew-BlC5RMTUEMA,746
|
|
45
|
+
davidkhala/ai/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
+
davidkhala/ai/google/adk.py,sha256=QwxYoOzT2Hol03V4NM0PF_HAzUGb4fB18VUAYacYbAY,657
|
|
47
|
+
davidkhala/ai/google/gemini.py,sha256=Xf4HDOOcK4-jEBERzuLnQNFsU61P2fFx4K0z-ijvNHE,214
|
|
48
|
+
davidkhala/ai/mistral/__init__.py,sha256=RpBOQFg67KFSuzaZ1LvuMtIpkfm-iTm6ZepkmHyggrg,371
|
|
49
|
+
davidkhala/ai/mistral/agent.py,sha256=hXHQj6MtxmR86Db4YbtMcdMi5NebX_Tg2bxYo_lL0sY,1652
|
|
50
|
+
davidkhala/ai/mistral/ai.py,sha256=SIIVjmR6oY4BjDTnYCiztkSJgfRF7_a3g21KoDQ0fVo,1324
|
|
51
|
+
davidkhala/ai/mistral/file.py,sha256=Y8RnaONasZX6zJDWzrG0Ez7epQ_BS3CKiIK8EqqX9YE,1402
|
|
52
|
+
davidkhala/ai/mistral/ocr.py,sha256=iImHiv784ZYdqKPwbUJhy7EL9WAXSpc4h4ixTZi3FHY,1736
|
|
53
|
+
davidkhala/ai/model/__init__.py,sha256=ODvM3qaEIjNJcJeU6Nkozj77LUWlC1HcPM-ifYVjA5s,490
|
|
54
|
+
davidkhala/ai/model/chat.py,sha256=1RgvdqMh7wK3bxiu5g3lDI89zVeuASSMKgeCJxqsiTI,2178
|
|
55
|
+
davidkhala/ai/model/embed.py,sha256=2W5Z-qKJUaROxuqV4yqqy7w666PDoh6RBj9gWFKWhUY,217
|
|
56
|
+
davidkhala/ai/model/garden.py,sha256=vcG6-fO0SJckNiPJ1wLJzsu6yKOIdQcVDARI9f9WQNg,178
|
|
57
|
+
davidkhala/ai/openai/__init__.py,sha256=-9SayyencR2nvGycYt_HF-8VqUXmQW9lIwYJV95RXCc,1443
|
|
58
|
+
davidkhala/ai/openai/azure.py,sha256=npF0GA-1jkKL6bsDyMrStkJODn1ShTsqdOKzsLu-mgc,3257
|
|
59
|
+
davidkhala/ai/openai/databricks.py,sha256=Z_ES3KlZuwMjMiGnlAxxrirLInQRVXj2KZs32MHXBbI,736
|
|
60
|
+
davidkhala/ai/openai/native.py,sha256=WhtpBCx_iGyy6tolGjJm1_gJtGo-dcmc_7QvnaxQ6WY,691
|
|
61
|
+
davidkhala/ai/openai/opik.py,sha256=ovodFNDoDO_ygX8_EmeqbZcu8PRTntzsNNQg4JoZKWo,257
|
|
62
|
+
davidkhala/ai/openrouter/__init__.py,sha256=8TLj1noeAvEzhowvkbLu2KUiR8KNijv8OMYRt6G7ApQ,1473
|
|
63
|
+
davidkhala_ai-0.2.2.dist-info/METADATA,sha256=pa6tpzTxuokcqYOsmvCx_oLdhS_JZ_QInQGC0PN7RY0,1837
|
|
64
|
+
davidkhala_ai-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
65
|
+
davidkhala_ai-0.2.2.dist-info/RECORD,,
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Iterable, TypedDict, Optional
|
|
6
|
-
from urllib.parse import urlparse
|
|
7
|
-
|
|
8
|
-
import requests
|
|
9
|
-
|
|
10
|
-
from davidkhala.ai.agent.dify.api import API, Iterator
|
|
11
|
-
from davidkhala.ai.agent.dify.model import Document as DocumentBase
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class DatasetDict(TypedDict):
|
|
15
|
-
id: str
|
|
16
|
-
name: str
|
|
17
|
-
description: str
|
|
18
|
-
provider: str
|
|
19
|
-
permission: str
|
|
20
|
-
data_source_type: str
|
|
21
|
-
indexing_technique: str
|
|
22
|
-
doc_form: str
|
|
23
|
-
runtime_mode: str
|
|
24
|
-
is_published: bool
|
|
25
|
-
enable_api: bool
|
|
26
|
-
# stats
|
|
27
|
-
app_count: int
|
|
28
|
-
document_count: int
|
|
29
|
-
word_count: int
|
|
30
|
-
total_documents: int
|
|
31
|
-
total_available_documents: int
|
|
32
|
-
# embedding
|
|
33
|
-
embedding_available: bool
|
|
34
|
-
embedding_model: str
|
|
35
|
-
embedding_model_provider: str
|
|
36
|
-
retrieval_model_dict: dict
|
|
37
|
-
external_retrieval_model: dict
|
|
38
|
-
external_knowledge_info: dict
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class Document(DocumentBase):
|
|
42
|
-
data_source_info: dict[str, str]
|
|
43
|
-
data_source_detail_dict: dict[str, dict]
|
|
44
|
-
dataset_process_rule_id: str
|
|
45
|
-
created_from: str
|
|
46
|
-
created_by: str
|
|
47
|
-
created_at: int
|
|
48
|
-
tokens: int
|
|
49
|
-
archived: bool
|
|
50
|
-
display_status: str
|
|
51
|
-
word_count: int
|
|
52
|
-
hit_count: int
|
|
53
|
-
doc_form: str
|
|
54
|
-
doc_metadata: dict
|
|
55
|
-
disabled_at: int
|
|
56
|
-
disabled_by: str
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class Dataset(API):
|
|
60
|
-
def __init__(self, api_key: str, base_url="https://api.dify.ai/v1"):
|
|
61
|
-
super().__init__(api_key, f"{base_url}/datasets")
|
|
62
|
-
|
|
63
|
-
def paginate_datasets(self, page=1, size=20):
|
|
64
|
-
r = self.request(self.base_url, "GET", params={
|
|
65
|
-
'page': page,
|
|
66
|
-
'limit': size,
|
|
67
|
-
})
|
|
68
|
-
return r
|
|
69
|
-
|
|
70
|
-
def list_datasets(self) -> Iterable[list[DatasetDict]]:
|
|
71
|
-
return Iterator(self.paginate_datasets, None)
|
|
72
|
-
|
|
73
|
-
@property
|
|
74
|
-
def ids(self):
|
|
75
|
-
for sub_list in self.list_datasets():
|
|
76
|
-
for dataset in sub_list:
|
|
77
|
-
yield dataset['id']
|
|
78
|
-
|
|
79
|
-
class Instance(API):
|
|
80
|
-
def __init__(self, d: Dataset, dataset_id: str):
|
|
81
|
-
super().__init__(d.api_key, f"{d.base_url}/{dataset_id}")
|
|
82
|
-
|
|
83
|
-
def get(self):
|
|
84
|
-
return self.request(self.base_url, "GET")
|
|
85
|
-
|
|
86
|
-
def upload(self, filename, *, path=None, url=None, document_id=None):
|
|
87
|
-
"""
|
|
88
|
-
don't work for .html
|
|
89
|
-
work for .md
|
|
90
|
-
"""
|
|
91
|
-
files = {}
|
|
92
|
-
if path:
|
|
93
|
-
with open(path, 'rb') as f:
|
|
94
|
-
content = f.read()
|
|
95
|
-
if not filename:
|
|
96
|
-
filename = os.path.basename(path)
|
|
97
|
-
elif url:
|
|
98
|
-
r = requests.get(url)
|
|
99
|
-
r.raise_for_status()
|
|
100
|
-
if not filename:
|
|
101
|
-
parsed_url = urlparse(url)
|
|
102
|
-
filename = Path(parsed_url.path).name
|
|
103
|
-
content = r.content
|
|
104
|
-
files['file'] = (filename, content)
|
|
105
|
-
if document_id:
|
|
106
|
-
# don't work for html
|
|
107
|
-
r = requests.post(f"{self.base_url}/documents/{document_id}/update-by-file", files=files,
|
|
108
|
-
**self.options)
|
|
109
|
-
else:
|
|
110
|
-
r = requests.post(f"{self.base_url}/document/create-by-file", files=files, **self.options)
|
|
111
|
-
r = self.on_response(r)
|
|
112
|
-
return r['document']
|
|
113
|
-
|
|
114
|
-
def paginate_documents(self, page=1, size=20):
|
|
115
|
-
return self.request(f"{self.base_url}/documents", "GET", params={
|
|
116
|
-
'page': page,
|
|
117
|
-
'limit': size
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
def list_documents(self) -> Iterable[Document]:
|
|
121
|
-
for document_batch in Iterator(self.paginate_documents, None):
|
|
122
|
-
for document in document_batch:
|
|
123
|
-
yield Document(**document)
|
|
124
|
-
|
|
125
|
-
def has_document(self, name) -> bool:
|
|
126
|
-
return any(name == item['name'] for row in self.list_documents() for item in row)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class ChunkDict(TypedDict):
|
|
130
|
-
id: str
|
|
131
|
-
position: int
|
|
132
|
-
document_id: str
|
|
133
|
-
content: str
|
|
134
|
-
sign_content: str # trimmed version of content
|
|
135
|
-
answer: Optional[str] # only used in QA chunk
|
|
136
|
-
word_count: int
|
|
137
|
-
tokens: int
|
|
138
|
-
keywords: Optional[list[str]]
|
|
139
|
-
index_node_id: str # chunk 在向量索引中的节点 ID
|
|
140
|
-
index_node_hash: str # hash of sign_content
|
|
141
|
-
hit_count: int
|
|
142
|
-
enabled: bool
|
|
143
|
-
status: str # 'completed'
|
|
144
|
-
created_at: int # timestamp
|
|
145
|
-
updated_at: int # timestamp
|
|
146
|
-
completed_at: int # timestamp
|
|
147
|
-
created_by: str # user id
|
|
148
|
-
child_chunks: list
|
|
149
|
-
error: Optional
|
|
150
|
-
stopped_at: Optional[int] # timestamp
|
|
151
|
-
disabled_at: Optional[int] # timestamp
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class Document(API):
|
|
155
|
-
def __init__(self, d: Dataset.Instance, document_id: str):
|
|
156
|
-
super().__init__(d.api_key, f"{d.base_url}/documents/{document_id}")
|
|
157
|
-
|
|
158
|
-
def exist(self):
|
|
159
|
-
try:
|
|
160
|
-
self.get()
|
|
161
|
-
return True
|
|
162
|
-
except requests.exceptions.HTTPError as e:
|
|
163
|
-
if e.response.status_code == 404:
|
|
164
|
-
return False
|
|
165
|
-
else:
|
|
166
|
-
raise e
|
|
167
|
-
|
|
168
|
-
def get(self):
|
|
169
|
-
return self.request(self.base_url, "GET")
|
|
170
|
-
|
|
171
|
-
def paginate_chunks(self, page=1, size=20):
|
|
172
|
-
return self.request(f"{self.base_url}/segments", "GET", params={
|
|
173
|
-
'page': page,
|
|
174
|
-
'limit': size
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
def list_chunks(self) -> Iterable[ChunkDict]:
|
|
178
|
-
for chunk_batch in Iterator(self.paginate_chunks, None):
|
|
179
|
-
for chunk in chunk_batch:
|
|
180
|
-
yield chunk
|
|
181
|
-
|
|
182
|
-
def delete(self):
|
|
183
|
-
if self.exist():
|
|
184
|
-
self.request(self.base_url, "DELETE")
|
|
185
|
-
class Chunk(API):
|
|
186
|
-
def __init__(self, d: Document, segment_id: str):
|
|
187
|
-
super().__init__(d.api_key, f"{d.base_url}/segments/{segment_id}")
|
|
188
|
-
def get(self):
|
|
189
|
-
r= self.request(self.base_url, "GET")
|
|
190
|
-
assert r['doc_form'] # optional value text_model
|
|
191
|
-
return r['data']
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|