davidkhala.ai 0.0.1__py3-none-any.whl → 0.0.3__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.
File without changes
File without changes
@@ -0,0 +1,68 @@
1
+ from enum import Enum
2
+ from http import HTTPStatus
3
+ from typing import List
4
+
5
+ from dashscope import Generation, TextEmbedding
6
+ from dashscope.api_entities.dashscope_response import DashScopeAPIResponse
7
+
8
+ from davidkhala.ai.model import AbstractClient
9
+
10
+
11
+ class ModelEnum(str, Enum):
12
+ BAILIAN = Generation.Models.bailian_v1
13
+ DOLLY = Generation.Models.dolly_12b_v2
14
+ TURBO = Generation.Models.qwen_turbo
15
+ PLUS = Generation.Models.qwen_plus
16
+ MAX = Generation.Models.qwen_max
17
+ EMBED = TextEmbedding.Models.text_embedding_v4
18
+
19
+
20
+ class API(AbstractClient):
21
+ """
22
+ Unsupported to use international base_url "https://dashscope-intl.aliyuncs.com"
23
+ """
24
+
25
+ model: ModelEnum
26
+
27
+ def __init__(self, api_key):
28
+ self.api_key = api_key
29
+
30
+ def as_embeddings(self, model=ModelEnum.EMBED):
31
+ super().as_embeddings(model)
32
+
33
+ @staticmethod
34
+ def _on_response(response:DashScopeAPIResponse):
35
+ if response.status_code == HTTPStatus.OK:
36
+ return response.output
37
+ else:
38
+ raise Exception(response)
39
+
40
+
41
+ def chat(self, user_prompt: str, **kwargs):
42
+
43
+ if not self.messages:
44
+ kwargs['prompt'] = user_prompt
45
+ else:
46
+ kwargs['messages'] = [
47
+ *self.messages,
48
+ {
49
+ "role": "user",
50
+ 'content': user_prompt
51
+ }
52
+ ]
53
+ # prompt 和 messages 是互斥的参数:如果你使用了 messages,就不要再传 prompt
54
+ r = Generation.call(
55
+ self.model,
56
+ api_key=self.api_key,
57
+ **kwargs
58
+ )
59
+ return API._on_response(r)
60
+
61
+ def encode(self, *_input: str)-> List[List[float]]:
62
+ r= TextEmbedding.call(
63
+ self.model,list(_input),
64
+ api_key= self.api_key,
65
+ )
66
+ r = API._on_response(r)
67
+
68
+ return [item['embedding'] for item in r['embeddings']]
@@ -3,7 +3,7 @@ from abc import abstractmethod, ABC
3
3
 
4
4
  import requests
5
5
 
6
-
6
+ # TODO Think openrouter as exceptional case
7
7
  class API(ABC):
8
8
  def __init__(self, api_key: str, base_url: str):
9
9
  self.base_url = base_url+'/v1'
@@ -16,7 +16,6 @@ class API(ABC):
16
16
  def free_models(self)->list[str]:
17
17
  ...
18
18
 
19
- @abstractmethod
20
19
  def pre_request(self, headers: dict, data: dict):
21
20
  data["model"] = self.model
22
21
  def chat(self, prompt, system_prompt: str = None):
davidkhala/ai/api/open.py CHANGED
@@ -24,7 +24,7 @@ class OpenRouter(API):
24
24
  if models is None:
25
25
  models = [self.free_models[0]]
26
26
  self.models = models
27
-
27
+ # TODO Hard to multi-model supports here
28
28
  def pre_request(self, headers: dict, data: dict):
29
29
  if self.leaderboard is not None:
30
30
  headers["HTTP-Referer"] = self.leaderboard['url'], # Optional. Site URL for rankings on openrouter.ai.
@@ -35,5 +35,3 @@ class SiliconFlow(API):
35
35
  def __init__(self, api_key: str, model: str):
36
36
  super().__init__(api_key, 'https://api.siliconflow.cn')
37
37
  self.model = model
38
- def pre_request(self, headers: dict, data: dict):
39
- super().pre_request(headers, data)
davidkhala/ai/model.py ADDED
@@ -0,0 +1,28 @@
1
+ from abc import ABC
2
+ from typing import Optional, List
3
+
4
+
5
+ class AbstractClient(ABC):
6
+ api_key: str
7
+ base_url: str
8
+ model: Optional[str]
9
+ messages = []
10
+
11
+ def as_chat(self, model: str, sys_prompt: str = None):
12
+ self.model = model
13
+ if sys_prompt is not None:
14
+ self.messages = [{"role": "system", "content": sys_prompt}]
15
+
16
+ def as_embeddings(self, model: str):
17
+ self.model = model
18
+
19
+ def chat(self, user_prompt: str, **kwargs):
20
+ ...
21
+
22
+ def encode(self, *_input: str) -> List[List[float]]:
23
+ ...
24
+ def connect(self):
25
+ ...
26
+
27
+ def disconnect(self):
28
+ ...
@@ -1,35 +1,25 @@
1
1
  import runpy
2
- from abc import ABC
3
- from typing import Union, Optional, Literal, List
2
+ from typing import Union, Literal, List
4
3
 
5
4
  from openai import OpenAI, AsyncOpenAI
6
5
 
6
+ from davidkhala.ai.model import AbstractClient
7
7
 
8
- class Client(ABC):
9
- api_key: str
10
- base_url: str
11
- model: Optional[str]
12
- messages = []
13
- client: OpenAI
14
-
15
- def as_chat(self, model, sys_prompt: str = None):
16
- self.model = model
17
- if sys_prompt is not None:
18
- self.messages = [{"role": "system", "content": sys_prompt}]
19
8
 
20
- def as_embeddings(self, model, encoding_format: str = "float"):
21
- self.model = model
9
+ class Client(AbstractClient):
10
+ client: OpenAI
11
+ encoding_format: Literal["float", "base64"] = "float"
22
12
 
23
13
  def connect(self):
24
14
  self.client.models.list()
25
15
 
26
- def encode(self, _input: str, _format: Literal["float", "base64"] = "float")-> List[float]:
16
+ def encode(self, *_input: str) -> List[List[float]]:
27
17
  response = self.client.embeddings.create(
28
18
  model=self.model,
29
- input=_input,
30
- encoding_format=_format
19
+ input=list(_input),
20
+ encoding_format=self.encoding_format
31
21
  )
32
- return response.data[0].embedding
22
+ return [item.embedding for item in response.data]
33
23
 
34
24
  def chat(self, user_prompt, image: str = None):
35
25
 
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: davidkhala.ai
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: misc AI modules
5
5
  Requires-Python: >=3.13
6
- Requires-Dist: opik
6
+ Provides-Extra: ali
7
+ Requires-Dist: dashscope; extra == 'ali'
7
8
  Provides-Extra: api
8
9
  Requires-Dist: requests; extra == 'api'
9
10
  Provides-Extra: google
@@ -15,3 +16,5 @@ Requires-Dist: langchain-openai; extra == 'langchain'
15
16
  Requires-Dist: langgraph; extra == 'langchain'
16
17
  Provides-Extra: openai
17
18
  Requires-Dist: openai; extra == 'openai'
19
+ Provides-Extra: telemetry
20
+ Requires-Dist: opik; (python_version < '3.14') and extra == 'telemetry'
@@ -0,0 +1,20 @@
1
+ davidkhala/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ davidkhala/ai/model.py,sha256=ujc88wQUP7SAyg9K8SQ45AuFOPFGtwAUyL05jYlUEBQ,657
3
+ davidkhala/ai/opik.py,sha256=YU1XuweMUAzUkhpjxhltt-SBBDBkR3z-PCNo0DqzBRs,39
4
+ davidkhala/ai/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ davidkhala/ai/agent/dify.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ davidkhala/ai/agent/langgraph.py,sha256=VEA2NQov_-KffTjgzO7nOIHiI4U9Y6enLTe3MQqKihc,1121
7
+ davidkhala/ai/ali/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ davidkhala/ai/ali/dashscope.py,sha256=b49unSTVXhjHCA0F1Qt6_-Zs7zjSgEetIcVK5E2nDMQ,1968
9
+ davidkhala/ai/api/__init__.py,sha256=PaLXWbFdaRvjqiNlAp0GR18e1zRflzNYfSpI5_eWbgU,2040
10
+ davidkhala/ai/api/open.py,sha256=pa4w_4b4EskwHrXoh4pqd83WuEYSv1peWktCjvzC6VA,1265
11
+ davidkhala/ai/api/siliconflow.py,sha256=Xkay52WuJJfE-7s1SoUIffez6qgYqigQ4JOwKg_zmv4,1217
12
+ davidkhala/ai/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ davidkhala/ai/google/adk.py,sha256=QwxYoOzT2Hol03V4NM0PF_HAzUGb4fB18VUAYacYbAY,657
14
+ davidkhala/ai/google/gemini.py,sha256=Xf4HDOOcK4-jEBERzuLnQNFsU61P2fFx4K0z-ijvNHE,214
15
+ davidkhala/ai/openai/__init__.py,sha256=SvQvUgVgw5vRQtF4S3WUYqg1DOzGSQ7BtHvTSEwkmpY,1597
16
+ davidkhala/ai/openai/azure.py,sha256=jAtZNW1d8ub3odhB_f1MXxM7MImg64MXDnqLm1-Idkk,828
17
+ davidkhala/ai/openai/native.py,sha256=-XuHn0KSQnuFdJ4jTwZla1ts5iOW2L2Hosfo8o8iip8,257
18
+ davidkhala_ai-0.0.3.dist-info/METADATA,sha256=7HcafXjgpnW4CcZ64avbZBIEPJwa70jr14k52w6P68o,678
19
+ davidkhala_ai-0.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ davidkhala_ai-0.0.3.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- davidkhala/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- davidkhala/ai/opik.py,sha256=YU1XuweMUAzUkhpjxhltt-SBBDBkR3z-PCNo0DqzBRs,39
3
- davidkhala/ai/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- davidkhala/ai/agent/langgraph.py,sha256=VEA2NQov_-KffTjgzO7nOIHiI4U9Y6enLTe3MQqKihc,1121
5
- davidkhala/ai/api/__init__.py,sha256=IKT7TmMUrfk6bllpsXdBd-w13lHgWADU5Qk5ln01DLY,2018
6
- davidkhala/ai/api/open.py,sha256=_63n7Trrvj5pK-ZCud3HIJ-cpZWDAPpCQUjXGusFdU0,1221
7
- davidkhala/ai/api/siliconflow.py,sha256=uts5K1TpBOg8Eo6UZkNJWktQPoolfmn2sID01wiac6s,1314
8
- davidkhala/ai/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- davidkhala/ai/google/adk.py,sha256=QwxYoOzT2Hol03V4NM0PF_HAzUGb4fB18VUAYacYbAY,657
10
- davidkhala/ai/google/gemini.py,sha256=Xf4HDOOcK4-jEBERzuLnQNFsU61P2fFx4K0z-ijvNHE,214
11
- davidkhala/ai/openai/__init__.py,sha256=GrgaO2NEoJKEWMc20yBbTx_-YikA0zRjJbtn0_j9RJs,1887
12
- davidkhala/ai/openai/azure.py,sha256=jAtZNW1d8ub3odhB_f1MXxM7MImg64MXDnqLm1-Idkk,828
13
- davidkhala/ai/openai/native.py,sha256=-XuHn0KSQnuFdJ4jTwZla1ts5iOW2L2Hosfo8o8iip8,257
14
- davidkhala_ai-0.0.1.dist-info/METADATA,sha256=-0mMOhqWaLneA3egQyWwWCkLgTevJTv6qjG-DY3nK-E,539
15
- davidkhala_ai-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- davidkhala_ai-0.0.1.dist-info/RECORD,,