diona 0.0.0__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.
Files changed (177) hide show
  1. diona-0.0.0/PKG-INFO +44 -0
  2. diona-0.0.0/README.md +23 -0
  3. diona-0.0.0/pyproject.toml +36 -0
  4. diona-0.0.0/setup.cfg +4 -0
  5. diona-0.0.0/src/diona/__init__.py +5 -0
  6. diona-0.0.0/src/diona/ai/client/base/__init__.py +19 -0
  7. diona-0.0.0/src/diona/ai/client/base/base.py +224 -0
  8. diona-0.0.0/src/diona/ai/client/base/base_ai_config.py +53 -0
  9. diona-0.0.0/src/diona/ai/client/base/base_chat.py +70 -0
  10. diona-0.0.0/src/diona/ai/client/base/base_chat_history.py +21 -0
  11. diona-0.0.0/src/diona/ai/client/base/base_client.py +85 -0
  12. diona-0.0.0/src/diona/ai/client/base/client_config.py +34 -0
  13. diona-0.0.0/src/diona/ai/client/base/interactive.py +25 -0
  14. diona-0.0.0/src/diona/ai/client/base/message.py +40 -0
  15. diona-0.0.0/src/diona/ai/client/simplecli/__init__.py +6 -0
  16. diona-0.0.0/src/diona/ai/client/simplecli/agent/__init__.py +1 -0
  17. diona-0.0.0/src/diona/ai/client/simplecli/agent/parser.py +51 -0
  18. diona-0.0.0/src/diona/ai/client/simplecli/agent/prompt.py +43 -0
  19. diona-0.0.0/src/diona/ai/client/simplecli/agent/system.py +124 -0
  20. diona-0.0.0/src/diona/ai/client/simplecli/command.py +36 -0
  21. diona-0.0.0/src/diona/ai/client/simplecli/config.py +143 -0
  22. diona-0.0.0/src/diona/ai/client/simplecli/core/__init__.py +1 -0
  23. diona-0.0.0/src/diona/ai/client/simplecli/core/command.py +151 -0
  24. diona-0.0.0/src/diona/ai/client/simplecli/core/engine.py +130 -0
  25. diona-0.0.0/src/diona/ai/client/simplecli/main.py +115 -0
  26. diona-0.0.0/src/diona/ai/client/simplecli/models.py +74 -0
  27. diona-0.0.0/src/diona/ai/client/simplecli/providers/__init__.py +1 -0
  28. diona-0.0.0/src/diona/ai/client/simplecli/providers/openai.py +161 -0
  29. diona-0.0.0/src/diona/ai/client/simplecli/session/__init__.py +1 -0
  30. diona-0.0.0/src/diona/ai/client/simplecli/session/manager.py +229 -0
  31. diona-0.0.0/src/diona/ai/client/simplecli/tools/__init__.py +1 -0
  32. diona-0.0.0/src/diona/ai/client/simplecli/tools/filesystem.py +178 -0
  33. diona-0.0.0/src/diona/ai/client/simplecli/tools/git.py +185 -0
  34. diona-0.0.0/src/diona/ai/client/simplecli/tools/manager.py +107 -0
  35. diona-0.0.0/src/diona/ai/client/simplecli/tools/shell.py +84 -0
  36. diona-0.0.0/src/diona/ai/client/simplecli/tools/websearch.py +98 -0
  37. diona-0.0.0/src/diona/ai/client/simplecli/ui/__init__.py +1 -0
  38. diona-0.0.0/src/diona/ai/client/simplecli/ui/console.py +171 -0
  39. diona-0.0.0/src/diona/ai/client/simplecli/ui/styles.py +46 -0
  40. diona-0.0.0/src/diona/ai/fakemodel/__init__.py +4 -0
  41. diona-0.0.0/src/diona/ai/fakemodel/core/FakeModel.py +58 -0
  42. diona-0.0.0/src/diona/ai/fakemodel/core/FakeModelExpander.py +65 -0
  43. diona-0.0.0/src/diona/ai/fakemodel/core/__init__.py +6 -0
  44. diona-0.0.0/src/diona/ai/fakemodel/core/analyzer.py +47 -0
  45. diona-0.0.0/src/diona/ai/fakemodel/core/corpus/__init__.py +0 -0
  46. diona-0.0.0/src/diona/ai/fakemodel/core/corpus/manager.py +23 -0
  47. diona-0.0.0/src/diona/ai/fakemodel/core/generation/__init__.py +0 -0
  48. diona-0.0.0/src/diona/ai/fakemodel/core/generation/generator.py +17 -0
  49. diona-0.0.0/src/diona/ai/fakemodel/core/intent/__init__.py +0 -0
  50. diona-0.0.0/src/diona/ai/fakemodel/core/intent/classifier.py +40 -0
  51. diona-0.0.0/src/diona/ai/fakemodel/core/io/__init__.py +0 -0
  52. diona-0.0.0/src/diona/ai/fakemodel/core/io/input_processor.py +16 -0
  53. diona-0.0.0/src/diona/ai/fakemodel/core/io/output_formatter.py +10 -0
  54. diona-0.0.0/src/diona/ai/fakemodel/core/loader.py +47 -0
  55. diona-0.0.0/src/diona/ai/fakemodel/core/models/__init__.py +0 -0
  56. diona-0.0.0/src/diona/ai/fakemodel/core/models/data_models.py +13 -0
  57. diona-0.0.0/src/diona/ai/fakemodel/defaultfakemodel.py +20 -0
  58. diona-0.0.0/src/diona/ai/fakemodel/models/Ganyu/fakemodelconfig.py +816 -0
  59. diona-0.0.0/src/diona/ai/fakemodel/models/Ganyu2/fakemodelconfig.py +2376 -0
  60. diona-0.0.0/src/diona/ai/fakemodel/models/default/fakemodelconfig.py +1540 -0
  61. diona-0.0.0/src/diona/ai/fakemodel/registry/__init__.py +3 -0
  62. diona-0.0.0/src/diona/ai/fakemodel/registry/registry.py +65 -0
  63. diona-0.0.0/src/diona/firstmeet/__init__.py +3 -0
  64. diona-0.0.0/src/diona/firstmeet/hello.py +2 -0
  65. diona-0.0.0/src/diona/project/__init__.py +5 -0
  66. diona-0.0.0/src/diona/project/bus/__init__.py +10 -0
  67. diona-0.0.0/src/diona/project/bus/bus.py +185 -0
  68. diona-0.0.0/src/diona/project/bus/interfaces.py +31 -0
  69. diona-0.0.0/src/diona/project/bus/message.py +54 -0
  70. diona-0.0.0/src/diona/project/cli/__init__.py +5 -0
  71. diona-0.0.0/src/diona/project/cli/builtin/__init__.py +9 -0
  72. diona-0.0.0/src/diona/project/cli/builtin/base.py +15 -0
  73. diona-0.0.0/src/diona/project/cli/builtin/date.py +20 -0
  74. diona-0.0.0/src/diona/project/cli/builtin/exit.py +17 -0
  75. diona-0.0.0/src/diona/project/cli/builtin/help.py +29 -0
  76. diona-0.0.0/src/diona/project/cli/builtin/list_commands.py +31 -0
  77. diona-0.0.0/src/diona/project/cli/builtin/time.py +20 -0
  78. diona-0.0.0/src/diona/project/cli/core/__init__.py +0 -0
  79. diona-0.0.0/src/diona/project/cli/core/command.py +36 -0
  80. diona-0.0.0/src/diona/project/cli/core/core.py +100 -0
  81. diona-0.0.0/src/diona/project/cli/core/task.py +127 -0
  82. diona-0.0.0/src/diona/project/cli/run.py +8 -0
  83. diona-0.0.0/src/diona/project/cli/ui/__init__.py +3 -0
  84. diona-0.0.0/src/diona/project/cli/ui/ui.py +33 -0
  85. diona-0.0.0/src/diona/project/command/__init__.py +7 -0
  86. diona-0.0.0/src/diona/project/command/alias.py +7 -0
  87. diona-0.0.0/src/diona/project/command/command_manager.py +105 -0
  88. diona-0.0.0/src/diona/project/command/models.py +37 -0
  89. diona-0.0.0/src/diona/project/command/registry.py +77 -0
  90. diona-0.0.0/src/diona/project/diona/__init__.py +5 -0
  91. diona-0.0.0/src/diona/project/diona/main.py +42 -0
  92. diona-0.0.0/src/diona/project/log/__init__.py +3 -0
  93. diona-0.0.0/src/diona/project/log/logger.py +61 -0
  94. diona-0.0.0/src/diona/project/scheduler/__init__.py +13 -0
  95. diona-0.0.0/src/diona/project/scheduler/executor.py +89 -0
  96. diona-0.0.0/src/diona/project/scheduler/interfaces.py +131 -0
  97. diona-0.0.0/src/diona/project/scheduler/manager.py +84 -0
  98. diona-0.0.0/src/diona/project/scheduler/scheduler.py +49 -0
  99. diona-0.0.0/src/diona/project/scheduler/task.py +90 -0
  100. diona-0.0.0/src/diona/project/shell/__init__.py +5 -0
  101. diona-0.0.0/src/diona/project/shell/config.py +25 -0
  102. diona-0.0.0/src/diona/project/shell/shell.py +228 -0
  103. diona-0.0.0/src/diona/project/storage/__init__.py +5 -0
  104. diona-0.0.0/src/diona/project/storage/cache.py +221 -0
  105. diona-0.0.0/src/diona/project/storage/interfaces.py +63 -0
  106. diona-0.0.0/src/diona/project/storage/storage.py +132 -0
  107. diona-0.0.0/src/diona/storage/hashfs/__init__.py +3 -0
  108. diona-0.0.0/src/diona/system/__init__.py +0 -0
  109. diona-0.0.0/src/diona/system/sensitive/__init__.py +0 -0
  110. diona-0.0.0/src/diona/system/sensitive/browser/__init__.py +15 -0
  111. diona-0.0.0/src/diona/system/sensitive/browser/cookies/__init__.py +9 -0
  112. diona-0.0.0/src/diona/system/sensitive/browser/cookies/base.py +35 -0
  113. diona-0.0.0/src/diona/system/sensitive/browser/cookies/chrome.py +125 -0
  114. diona-0.0.0/src/diona/system/sensitive/browser/cookies/edge.py +133 -0
  115. diona-0.0.0/src/diona/system/sensitive/browser/history/__init__.py +9 -0
  116. diona-0.0.0/src/diona/system/sensitive/browser/history/base.py +35 -0
  117. diona-0.0.0/src/diona/system/sensitive/browser/history/chrome.py +117 -0
  118. diona-0.0.0/src/diona/system/sensitive/browser/history/edge.py +125 -0
  119. diona-0.0.0/src/diona/system/sensitive/browser/logindata/__init__.py +9 -0
  120. diona-0.0.0/src/diona/system/sensitive/browser/logindata/base.py +35 -0
  121. diona-0.0.0/src/diona/system/sensitive/browser/logindata/chrome.py +141 -0
  122. diona-0.0.0/src/diona/system/sensitive/browser/logindata/edge.py +141 -0
  123. diona-0.0.0/src/diona/system/sensitive/browser/models/__init__.py +13 -0
  124. diona-0.0.0/src/diona/system/sensitive/browser/models/cookies.py +77 -0
  125. diona-0.0.0/src/diona/system/sensitive/browser/models/history.py +57 -0
  126. diona-0.0.0/src/diona/system/sensitive/browser/models/logindata.py +72 -0
  127. diona-0.0.0/src/diona/system/sensitive/core/__init__.py +7 -0
  128. diona-0.0.0/src/diona/system/sensitive/core/info_store.py +75 -0
  129. diona-0.0.0/src/diona/system/sensitive/info/NetworkConfigInfo.py +30 -0
  130. diona-0.0.0/src/diona/system/sensitive/info/NetworkConfigInfoImpl.py +216 -0
  131. diona-0.0.0/src/diona/system/sensitive/info/SystemVersionInfo.py +31 -0
  132. diona-0.0.0/src/diona/system/sensitive/info/SystemVersionInfoImpl.py +214 -0
  133. diona-0.0.0/src/diona/system/sensitive/info/WirelessNetworkInfo.py +30 -0
  134. diona-0.0.0/src/diona/system/sensitive/info/WirelessNetworkInfoImpl.py +181 -0
  135. diona-0.0.0/src/diona/system/sensitive/info/__init__.py +20 -0
  136. diona-0.0.0/src/diona/system/sensitive/info/constants/NetworkConfigInfoConstants.py +55 -0
  137. diona-0.0.0/src/diona/system/sensitive/info/constants/SystemVersionInfoConstants.py +53 -0
  138. diona-0.0.0/src/diona/system/sensitive/info/constants/WirelessNetworkInfoConstants.py +33 -0
  139. diona-0.0.0/src/diona/system/sensitive/info/models/NetworkConfigInfo.py +54 -0
  140. diona-0.0.0/src/diona/system/sensitive/info/models/SystemVersionInfo.py +78 -0
  141. diona-0.0.0/src/diona/system/sensitive/info/models/WirelessNetworkInfo.py +23 -0
  142. diona-0.0.0/src/diona/system/sensitive/runcontext/__init__.py +21 -0
  143. diona-0.0.0/src/diona/system/sensitive/runcontext/constants.py +45 -0
  144. diona-0.0.0/src/diona/system/sensitive/runcontext/context.py +111 -0
  145. diona-0.0.0/src/diona/system/sensitive/runcontext/models.py +35 -0
  146. diona-0.0.0/src/diona/system/sensitive/runcontext/utils.py +83 -0
  147. diona-0.0.0/src/diona/tools/__init__.py +1 -0
  148. diona-0.0.0/src/diona/tools/crawler/__init__.py +1 -0
  149. diona-0.0.0/src/diona/tools/crawler/base_spider.py +320 -0
  150. diona-0.0.0/src/diona/tools/crawler/cookie_manager.py +124 -0
  151. diona-0.0.0/src/diona/tools/crawler/models.py +66 -0
  152. diona-0.0.0/src/diona/tools/crawler/zhihu/__init__.py +3 -0
  153. diona-0.0.0/src/diona/tools/crawler/zhihu/models.py +43 -0
  154. diona-0.0.0/src/diona/tools/crawler/zhihu/zhihu_spider.py +453 -0
  155. diona-0.0.0/src/diona/tools/fakedelete/__init__.py +5 -0
  156. diona-0.0.0/src/diona/tools/fakedelete/command.py +60 -0
  157. diona-0.0.0/src/diona/tools/fakedelete/constants.py +11 -0
  158. diona-0.0.0/src/diona/tools/fakedelete/processor.py +45 -0
  159. diona-0.0.0/src/diona/tools/fakedelete/queue.py +73 -0
  160. diona-0.0.0/src/diona/tools/fakedelete/scanner.py +87 -0
  161. diona-0.0.0/src/diona/tools/fakeinstall/__init__.py +5 -0
  162. diona-0.0.0/src/diona/tools/fakeinstall/command.py +125 -0
  163. diona-0.0.0/src/diona/tools/fakeinstall/config.py +86 -0
  164. diona-0.0.0/src/diona/tools/fakeinstall/constants.py +149 -0
  165. diona-0.0.0/src/diona/tools/fakeinstall/executor.py +115 -0
  166. diona-0.0.0/src/diona/tools/fakeinstall/generator.py +94 -0
  167. diona-0.0.0/src/diona/tools/fakeinstall/models.py +13 -0
  168. diona-0.0.0/src/diona/tools/fakeinstall/utils.py +34 -0
  169. diona-0.0.0/src/diona/tools/program/__init__.py +7 -0
  170. diona-0.0.0/src/diona/tools/program/command.py +187 -0
  171. diona-0.0.0/src/diona/tools/program/file_time_modifier.py +294 -0
  172. diona-0.0.0/src/diona.egg-info/PKG-INFO +44 -0
  173. diona-0.0.0/src/diona.egg-info/SOURCES.txt +175 -0
  174. diona-0.0.0/src/diona.egg-info/dependency_links.txt +1 -0
  175. diona-0.0.0/src/diona.egg-info/entry_points.txt +2 -0
  176. diona-0.0.0/src/diona.egg-info/requires.txt +10 -0
  177. diona-0.0.0/src/diona.egg-info/top_level.txt +1 -0
diona-0.0.0/PKG-INFO ADDED
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: diona
3
+ Version: 0.0.0
4
+ Summary: A Python package named diona
5
+ Project-URL: Homepage, https://github.com/yourusername/diona
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: openai
12
+ Requires-Dist: pyyaml
13
+ Requires-Dist: python-dotenv
14
+ Requires-Dist: playwright
15
+ Requires-Dist: beautifulsoup4
16
+ Requires-Dist: rich
17
+ Requires-Dist: typer
18
+ Requires-Dist: GitPython
19
+ Requires-Dist: requests
20
+ Requires-Dist: jieba
21
+
22
+ # diona
23
+
24
+ A Python package named diona.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install diona
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```python
35
+ import diona
36
+
37
+ print(diona.__version__)
38
+ ```
39
+
40
+ ## Development
41
+
42
+ ```bash
43
+ pip install -e .
44
+ ```
diona-0.0.0/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # diona
2
+
3
+ A Python package named diona.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install diona
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ import diona
15
+
16
+ print(diona.__version__)
17
+ ```
18
+
19
+ ## Development
20
+
21
+ ```bash
22
+ pip install -e .
23
+ ```
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "diona"
7
+ version = "0.0.0"
8
+ description = "A Python package named diona"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Operating System :: OS Independent",
15
+ ]
16
+ dependencies = [
17
+ "openai",
18
+ "pyyaml",
19
+ "python-dotenv",
20
+ "playwright",
21
+ "beautifulsoup4",
22
+ "rich",
23
+ "typer",
24
+ "GitPython",
25
+ "requests",
26
+ "jieba"
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/yourusername/diona"
31
+
32
+ [tool.setuptools.packages.find]
33
+ where = ["src"]
34
+
35
+ [project.scripts]
36
+ diona = "diona.project.diona.main:main"
diona-0.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ __version__ = "0.1.0"
2
+
3
+ from diona.firstmeet import hello_diona
4
+
5
+ __all__ = ["hello_diona", "__version__"]
@@ -0,0 +1,19 @@
1
+ from .base_ai_config import BaseAIConfig
2
+ from .base_chat import BaseChat
3
+ from .base_chat_history import BaseChatHistory
4
+ from .client_config import ClientConfig
5
+ from .base_client import BaseClient
6
+ from .message import SingleChatMessage, ChatMessage, StreamingChatMessage
7
+ from .interactive import interactive_chat
8
+
9
+ __all__ = [
10
+ 'BaseAIConfig',
11
+ 'BaseChat',
12
+ 'BaseChatHistory',
13
+ 'ClientConfig',
14
+ 'BaseClient',
15
+ 'SingleChatMessage',
16
+ 'ChatMessage',
17
+ 'StreamingChatMessage',
18
+ 'interactive_chat'
19
+ ]
@@ -0,0 +1,224 @@
1
+ import os
2
+ import yaml
3
+ from dotenv import load_dotenv
4
+ from openai import OpenAI
5
+
6
+ class BaseAIConfig:
7
+ def __init__(self):
8
+ load_dotenv()
9
+ self.config = self._load_config()
10
+ self.base_url = self._get_config_value('diona.ai.modelset.base-url')
11
+ self.api_key = self._get_api_key()
12
+ self.model = self._get_config_value('diona.ai.modelset.model')
13
+ self.proxy = self._get_config_value('diona.ai.clientset.proxy', False)
14
+ self.use_proxy = self._get_config_value('diona.ai.clientset.use-proxy', False)
15
+
16
+ def _load_config(self):
17
+ config_path = os.path.join(os.getcwd(), 'config.yml')
18
+ if os.path.exists(config_path):
19
+ with open(config_path, 'r', encoding='utf-8') as f:
20
+ return yaml.safe_load(f)
21
+ return {}
22
+
23
+ def _get_config_value(self, key, default=None):
24
+ keys = key.split('.')
25
+ value = self.config
26
+ for k in keys:
27
+ if isinstance(value, dict) and k in value:
28
+ value = value[k]
29
+ else:
30
+ return default
31
+ return value
32
+
33
+ def _get_api_key(self):
34
+ # Priority: 1. Environment variable 2. .env file 3. config.yml
35
+ api_key = os.environ.get('OPENAI_API_KEY')
36
+ if api_key:
37
+ return api_key
38
+ api_key = self._get_config_value('diona.ai.modelset.api-key')
39
+ return api_key
40
+
41
+ def get_base_url(self):
42
+ return self.base_url
43
+
44
+ def get_api_key(self):
45
+ return self.api_key
46
+
47
+ def get_model(self):
48
+ return self.model
49
+
50
+ def get_proxy(self):
51
+ return self.proxy
52
+
53
+ def is_use_proxy(self):
54
+ return self.use_proxy
55
+
56
+ class BaseChat:
57
+ def __init__(self, config):
58
+ self.config = config
59
+ self.client = self._create_client()
60
+
61
+ def _create_client(self):
62
+ kwargs = {
63
+ 'api_key': self.config.get_api_key(),
64
+ 'base_url': self.config.get_base_url()
65
+ }
66
+ if self.config.is_use_proxy() and self.config.get_proxy():
67
+ kwargs['http_client'] = {
68
+ 'proxy': self.config.get_proxy()
69
+ }
70
+ return OpenAI(**kwargs)
71
+
72
+ def chat(self, chat_message):
73
+ response = self.client.chat.completions.create(
74
+ model=self.config.get_model(),
75
+ messages=chat_message.to_ai_messages()
76
+ )
77
+ ai_response = response.choices[0].message
78
+ metadata = {
79
+ 'id': response.id,
80
+ 'created': response.created,
81
+ 'model': response.model,
82
+ 'usage': {
83
+ 'prompt_tokens': response.usage.prompt_tokens,
84
+ 'completion_tokens': response.usage.completion_tokens,
85
+ 'total_tokens': response.usage.total_tokens
86
+ }
87
+ }
88
+ return SingleChatMessage(ai_response.role, ai_response.content, metadata)
89
+
90
+ class SingleChatMessage:
91
+ def __init__(self, role, content, metadata=None):
92
+ self.role = role
93
+ self.content = content
94
+ self.metadata = metadata or {}
95
+
96
+ @classmethod
97
+ def from_text(cls, text, role='user'):
98
+ return cls(role, text)
99
+
100
+ def to_ai_message(self):
101
+ return {
102
+ 'role': self.role,
103
+ 'content': self.content
104
+ }
105
+
106
+ class BaseChatHistory:
107
+ def __init__(self, max_messages=6):
108
+ self.max_messages = max_messages
109
+ self.messages = []
110
+
111
+ def add_message(self, message):
112
+ self.messages.append(message)
113
+ if len(self.messages) > self.max_messages:
114
+ self.messages.pop(0)
115
+
116
+ def get_messages(self):
117
+ return self.messages
118
+
119
+ def get_chat_message(self):
120
+ return ChatMessage(self.messages)
121
+
122
+ def persist(self):
123
+ # To be implemented by subclass
124
+ pass
125
+
126
+ class ClientConfig:
127
+ def __init__(self):
128
+ self.config = self._load_config()
129
+ self.prompt_path = self._get_config_value('diona.ai.clientset.prompt')
130
+ self.system_prompt = self._load_system_prompt()
131
+
132
+ def _load_config(self):
133
+ config_path = os.path.join(os.getcwd(), 'config.yml')
134
+ if os.path.exists(config_path):
135
+ with open(config_path, 'r', encoding='utf-8') as f:
136
+ return yaml.safe_load(f)
137
+ return {}
138
+
139
+ def _get_config_value(self, key, default=None):
140
+ keys = key.split('.')
141
+ value = self.config
142
+ for k in keys:
143
+ if isinstance(value, dict) and k in value:
144
+ value = value[k]
145
+ else:
146
+ return default
147
+ return value
148
+
149
+ def _load_system_prompt(self):
150
+ if self.prompt_path and os.path.exists(self.prompt_path):
151
+ with open(self.prompt_path, 'r', encoding='utf-8') as f:
152
+ return f.read().strip()
153
+ return "You are a helpful assistant"
154
+
155
+ def get_system_prompt(self):
156
+ return self.system_prompt
157
+
158
+ class BaseClient:
159
+ def __init__(self, base_chat, base_chat_history, client_config):
160
+ self.base_chat = base_chat
161
+ self.base_chat_history = base_chat_history
162
+ self.client_config = client_config
163
+ self.session_map = {}
164
+
165
+ def chat(self, session_id, user_input):
166
+ if isinstance(user_input, str):
167
+ user_message = SingleChatMessage.from_text(user_input, 'user')
168
+ else:
169
+ user_message = user_input
170
+
171
+ if session_id not in self.session_map:
172
+ self.session_map[session_id] = BaseChatHistory()
173
+
174
+ chat_history = self.session_map[session_id]
175
+ chat_history.add_message(user_message)
176
+
177
+ # Get current messages and add system prompt
178
+ current_messages = chat_history.get_messages()
179
+ system_prompt = self.client_config.get_system_prompt()
180
+ system_message = SingleChatMessage('system', system_prompt)
181
+
182
+ # Create chat message with system prompt at the beginning
183
+ messages_with_system = [system_message] + current_messages
184
+ chat_message = ChatMessage(messages_with_system)
185
+
186
+ # Get AI response
187
+ ai_response = self.base_chat.chat(chat_message)
188
+
189
+ # Add AI response to history
190
+ chat_history.add_message(ai_response)
191
+
192
+ return ai_response
193
+
194
+ @classmethod
195
+ def create(cls):
196
+ ai_config = BaseAIConfig()
197
+ base_chat = BaseChat(ai_config)
198
+ base_chat_history = BaseChatHistory()
199
+ client_config = ClientConfig()
200
+ return cls(base_chat, base_chat_history, client_config)
201
+
202
+ class ChatMessage:
203
+ def __init__(self, messages):
204
+ self.messages = messages
205
+
206
+ def to_ai_messages(self):
207
+ return [msg.to_ai_message() for msg in self.messages]
208
+
209
+ def interactive_chat():
210
+ client = BaseClient.create()
211
+ session_id = "default"
212
+
213
+ print("Welcome to Diona AI Chat!")
214
+ print("Type 'exit' to quit.")
215
+
216
+ while True:
217
+ user_input = input("<diona@user> ")
218
+ if user_input.strip().lower() == "exit":
219
+ print("Goodbye!")
220
+ break
221
+
222
+ response = client.chat(session_id, user_input)
223
+ print(f"<@assistant> {response.content}")
224
+ print()
@@ -0,0 +1,53 @@
1
+ import os
2
+ import yaml
3
+ from dotenv import load_dotenv
4
+
5
+ class BaseAIConfig:
6
+ def __init__(self):
7
+ load_dotenv()
8
+ self.config = self._load_config()
9
+ self.base_url = self._get_config_value('diona.ai.modelset.base-url')
10
+ self.api_key = self._get_api_key()
11
+ self.model = self._get_config_value('diona.ai.modelset.model')
12
+ self.proxy = self._get_config_value('diona.ai.clientset.proxy', False)
13
+ self.use_proxy = self._get_config_value('diona.ai.clientset.use-proxy', False)
14
+
15
+ def _load_config(self):
16
+ config_path = os.path.join(os.getcwd(), 'config.yml')
17
+ if os.path.exists(config_path):
18
+ with open(config_path, 'r', encoding='utf-8') as f:
19
+ return yaml.safe_load(f)
20
+ return {}
21
+
22
+ def _get_config_value(self, key, default=None):
23
+ keys = key.split('.')
24
+ value = self.config
25
+ for k in keys:
26
+ if isinstance(value, dict) and k in value:
27
+ value = value[k]
28
+ else:
29
+ return default
30
+ return value
31
+
32
+ def _get_api_key(self):
33
+ # Priority: 1. Environment variable 2. .env file 3. config.yml
34
+ api_key = os.environ.get('OPENAI_API_KEY')
35
+ if api_key:
36
+ return api_key
37
+ api_key = self._get_config_value('diona.ai.modelset.api-key')
38
+ return api_key
39
+
40
+ def get_base_url(self):
41
+ return self.base_url
42
+
43
+ def get_api_key(self):
44
+ return self.api_key
45
+
46
+ def get_model(self):
47
+ return self.model
48
+
49
+ def get_proxy(self):
50
+ return self.proxy
51
+
52
+ def is_use_proxy(self):
53
+ return self.use_proxy
@@ -0,0 +1,70 @@
1
+ from openai import OpenAI
2
+ from .message import SingleChatMessage
3
+
4
+ class BaseChat:
5
+ def __init__(self, config):
6
+ self.config = config
7
+ self.client = self._create_client()
8
+
9
+ def _create_client(self):
10
+ kwargs = {
11
+ 'api_key': self.config.get_api_key(),
12
+ 'base_url': self.config.get_base_url()
13
+ }
14
+ if self.config.is_use_proxy() and self.config.get_proxy():
15
+ kwargs['proxy'] = self.config.get_proxy()
16
+ return OpenAI(**kwargs)
17
+
18
+ def chat(self, chat_message):
19
+ response = self.client.chat.completions.create(
20
+ model=self.config.get_model(),
21
+ messages=chat_message.to_ai_messages()
22
+ )
23
+ ai_response = response.choices[0].message
24
+ metadata = {
25
+ 'id': response.id,
26
+ 'created': response.created,
27
+ 'model': response.model,
28
+ 'usage': {
29
+ 'prompt_tokens': response.usage.prompt_tokens,
30
+ 'completion_tokens': response.usage.completion_tokens,
31
+ 'total_tokens': response.usage.total_tokens
32
+ }
33
+ }
34
+ return SingleChatMessage(ai_response.role, ai_response.content, metadata)
35
+
36
+ def chat_stream(self, chat_message):
37
+ response = self.client.chat.completions.create(
38
+ model=self.config.get_model(),
39
+ messages=chat_message.to_ai_messages(),
40
+ stream=True
41
+ )
42
+
43
+ full_content = ""
44
+ role = None
45
+ metadata = {
46
+ 'id': None,
47
+ 'created': None,
48
+ 'model': None
49
+ }
50
+
51
+ for chunk in response:
52
+ if chunk.choices:
53
+ choice = chunk.choices[0]
54
+ if choice.delta:
55
+ if choice.delta.role:
56
+ role = choice.delta.role
57
+ if choice.delta.content:
58
+ content_chunk = choice.delta.content
59
+ full_content += content_chunk
60
+ yield content_chunk
61
+
62
+ # Capture metadata from the first chunk
63
+ if not metadata['id']:
64
+ metadata['id'] = chunk.id
65
+ metadata['created'] = chunk.created
66
+ metadata['model'] = chunk.model
67
+
68
+ # After streaming is complete, yield the final message object
69
+ if role and full_content:
70
+ yield SingleChatMessage(role, full_content, metadata)
@@ -0,0 +1,21 @@
1
+ from .message import ChatMessage
2
+
3
+ class BaseChatHistory:
4
+ def __init__(self, max_messages=6):
5
+ self.max_messages = max_messages
6
+ self.messages = []
7
+
8
+ def add_message(self, message):
9
+ self.messages.append(message)
10
+ if len(self.messages) > self.max_messages:
11
+ self.messages.pop(0)
12
+
13
+ def get_messages(self):
14
+ return self.messages
15
+
16
+ def get_chat_message(self):
17
+ return ChatMessage(self.messages)
18
+
19
+ def persist(self):
20
+ # To be implemented by subclass
21
+ pass
@@ -0,0 +1,85 @@
1
+ from .base_ai_config import BaseAIConfig
2
+ from .base_chat import BaseChat
3
+ from .base_chat_history import BaseChatHistory
4
+ from .client_config import ClientConfig
5
+ from .message import SingleChatMessage, ChatMessage
6
+
7
+ class BaseClient:
8
+ def __init__(self, base_chat, base_chat_history, client_config):
9
+ self.base_chat = base_chat
10
+ self.base_chat_history = base_chat_history
11
+ self.client_config = client_config
12
+ self.session_map = {}
13
+
14
+ def chat(self, session_id, user_input):
15
+ if isinstance(user_input, str):
16
+ user_message = SingleChatMessage.from_text(user_input, 'user')
17
+ else:
18
+ user_message = user_input
19
+
20
+ if session_id not in self.session_map:
21
+ self.session_map[session_id] = BaseChatHistory()
22
+
23
+ chat_history = self.session_map[session_id]
24
+ chat_history.add_message(user_message)
25
+
26
+ # Get current messages and add system prompt
27
+ current_messages = chat_history.get_messages()
28
+ system_prompt = self.client_config.get_system_prompt()
29
+ system_message = SingleChatMessage('system', system_prompt)
30
+
31
+ # Create chat message with system prompt at the beginning
32
+ messages_with_system = [system_message] + current_messages
33
+ chat_message = ChatMessage(messages_with_system)
34
+
35
+ # Get AI response
36
+ ai_response = self.base_chat.chat(chat_message)
37
+
38
+ # Add AI response to history
39
+ chat_history.add_message(ai_response)
40
+
41
+ return ai_response
42
+
43
+ def chat_stream(self, session_id, user_input):
44
+ if isinstance(user_input, str):
45
+ user_message = SingleChatMessage.from_text(user_input, 'user')
46
+ else:
47
+ user_message = user_input
48
+
49
+ if session_id not in self.session_map:
50
+ self.session_map[session_id] = BaseChatHistory()
51
+
52
+ chat_history = self.session_map[session_id]
53
+ chat_history.add_message(user_message)
54
+
55
+ # Get current messages and add system prompt
56
+ current_messages = chat_history.get_messages()
57
+ system_prompt = self.client_config.get_system_prompt()
58
+ system_message = SingleChatMessage('system', system_prompt)
59
+
60
+ # Create chat message with system prompt at the beginning
61
+ messages_with_system = [system_message] + current_messages
62
+ chat_message = ChatMessage(messages_with_system)
63
+
64
+ # Get AI response stream
65
+ ai_response = None
66
+ for chunk in self.base_chat.chat_stream(chat_message):
67
+ if isinstance(chunk, SingleChatMessage):
68
+ # This is the final message object
69
+ ai_response = chunk
70
+ else:
71
+ # This is a content chunk
72
+ yield chunk
73
+
74
+ # Add AI response to history
75
+ if ai_response:
76
+ chat_history.add_message(ai_response)
77
+ yield ai_response
78
+
79
+ @classmethod
80
+ def create(cls):
81
+ ai_config = BaseAIConfig()
82
+ base_chat = BaseChat(ai_config)
83
+ base_chat_history = BaseChatHistory()
84
+ client_config = ClientConfig()
85
+ return cls(base_chat, base_chat_history, client_config)
@@ -0,0 +1,34 @@
1
+ import os
2
+ import yaml
3
+
4
+ class ClientConfig:
5
+ def __init__(self):
6
+ self.config = self._load_config()
7
+ self.prompt_path = self._get_config_value('diona.ai.clientset.prompt')
8
+ self.system_prompt = self._load_system_prompt()
9
+
10
+ def _load_config(self):
11
+ config_path = os.path.join(os.getcwd(), 'config.yml')
12
+ if os.path.exists(config_path):
13
+ with open(config_path, 'r', encoding='utf-8') as f:
14
+ return yaml.safe_load(f)
15
+ return {}
16
+
17
+ def _get_config_value(self, key, default=None):
18
+ keys = key.split('.')
19
+ value = self.config
20
+ for k in keys:
21
+ if isinstance(value, dict) and k in value:
22
+ value = value[k]
23
+ else:
24
+ return default
25
+ return value
26
+
27
+ def _load_system_prompt(self):
28
+ if self.prompt_path and os.path.exists(self.prompt_path):
29
+ with open(self.prompt_path, 'r', encoding='utf-8') as f:
30
+ return f.read().strip()
31
+ return "You are a helpful assistant"
32
+
33
+ def get_system_prompt(self):
34
+ return self.system_prompt
@@ -0,0 +1,25 @@
1
+ from .base_client import BaseClient
2
+
3
+ def interactive_chat():
4
+ client = BaseClient.create()
5
+ session_id = "default"
6
+
7
+ print("Welcome to Diona AI Chat!")
8
+ print("Type 'exit' to quit.")
9
+
10
+ while True:
11
+ user_input = input("<diona@user> ")
12
+ if user_input.strip().lower() == "exit":
13
+ print("Goodbye!")
14
+ break
15
+
16
+ print("<@assistant> ", end="", flush=True)
17
+
18
+ # Use streaming chat
19
+ for chunk in client.chat_stream(session_id, user_input):
20
+ if isinstance(chunk, str):
21
+ # This is a content chunk, print it immediately
22
+ print(chunk, end="", flush=True)
23
+
24
+ print()
25
+ print()
@@ -0,0 +1,40 @@
1
+ class SingleChatMessage:
2
+ def __init__(self, role, content, metadata=None):
3
+ self.role = role
4
+ self.content = content
5
+ self.metadata = metadata or {}
6
+
7
+ @classmethod
8
+ def from_text(cls, text, role='user'):
9
+ return cls(role, text)
10
+
11
+ def to_ai_message(self):
12
+ return {
13
+ 'role': self.role,
14
+ 'content': self.content
15
+ }
16
+
17
+ class ChatMessage:
18
+ def __init__(self, messages):
19
+ self.messages = messages
20
+
21
+ def to_ai_messages(self):
22
+ return [msg.to_ai_message() for msg in self.messages]
23
+
24
+ class StreamingChatMessage:
25
+ def __init__(self, role=None):
26
+ self.role = role
27
+ self.content = ""
28
+ self.metadata = {}
29
+
30
+ def add_chunk(self, chunk):
31
+ self.content += chunk
32
+
33
+ def set_role(self, role):
34
+ self.role = role
35
+
36
+ def set_metadata(self, metadata):
37
+ self.metadata = metadata
38
+
39
+ def to_single_chat_message(self):
40
+ return SingleChatMessage(self.role, self.content, self.metadata)