emilia 0.1.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.
emilia-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.5
2
+ Name: emilia
3
+ Version: 0.1.0
4
+ Requires-Dist: ddgs
5
+ Requires-Dist: kopilogs
6
+ Requires-Dist: ollama
7
+ Requires-Dist: trafilatura
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = [
3
+ "hatchling",
4
+ ]
5
+ build-backend = "hatchling.build"
6
+
7
+ [project]
8
+ name = "emilia"
9
+ version = "0.1.0"
10
+ dependencies = [
11
+ "ollama",
12
+ "ddgs",
13
+ "kopilogs",
14
+ "trafilatura",
15
+ ]
16
+
17
+ [project.scripts]
18
+ emilia = "emilia.main:main"
19
+
20
+ [tool.kuvy.run-paths]
21
+ main = "src/emilia/main.py"
22
+ tests = "tests/tests.py"
File without changes
@@ -0,0 +1,89 @@
1
+ from ollama import (
2
+ chat,
3
+ Message,
4
+ ChatResponse,
5
+ )
6
+ from kopilogs.paint import paint
7
+
8
+ from typing import Sequence
9
+
10
+ from emilia.tools import (
11
+ search_internet,
12
+ what_time_is_it,
13
+ testing,
14
+ )
15
+ from emilia.hardcoded import context
16
+
17
+ class Emilia:
18
+ def __init__(self, model: str):
19
+ self.model = model
20
+ self.context = []
21
+ self._append_context("system", context)
22
+ self.tools = {
23
+ "search_internet": search_internet,
24
+ "testing": testing,
25
+ "what_time_is_it": what_time_is_it,
26
+ }
27
+
28
+ def talk(self) -> str:
29
+ while True:
30
+ request = input(paint(">>> ").bold().magenta())
31
+ self._append_context("user", request)
32
+
33
+ response = self._generate_content()
34
+ tool_calls = response.message.tool_calls
35
+ content = response.message.content
36
+ self._append_context("assistant", response.message)
37
+
38
+ if tool_calls is not None:
39
+ while True:
40
+ response_tool = self._handle_tool_call(tool_calls)
41
+ self._append_context("assistant", response_tool.message)
42
+
43
+ if response_tool.message.tool_calls is None:
44
+ content = response_tool.message.content
45
+ break
46
+
47
+ tool_calls = response_tool.message.tool_calls
48
+
49
+ print()
50
+ paint(">>> ", end="").bold().green().show()
51
+ print(content)
52
+ print()
53
+
54
+ def _handle_tool_call(self, tool_calls: Sequence) -> ChatResponse:
55
+ for tc in tool_calls:
56
+ result = self.tools[tc.function.name](**tc.function.arguments)
57
+ self._append_context("tool", result, tool_call=tc.function.name)
58
+
59
+ return self._generate_content()
60
+
61
+ def _generate_content(self) -> ChatResponse:
62
+ return chat(
63
+ model=self.model,
64
+ messages=self.context,
65
+ tools=list(self.tools.values()),
66
+ )
67
+
68
+ def _append_context(
69
+ self,
70
+ role: str,
71
+ content: str | Message,
72
+ tool_call: str | None = None,
73
+ ):
74
+ if type(content) == Message:
75
+ self.context.append(content)
76
+ return
77
+
78
+ if role == "tool" and tool_call is not None:
79
+ self.context.append({
80
+ "role": role,
81
+ "tool_name": tool_call,
82
+ "content": content,
83
+ })
84
+ return
85
+
86
+ self.context.append({
87
+ "role": role,
88
+ "content": content,
89
+ })
@@ -0,0 +1,18 @@
1
+ import datetime
2
+
3
+ context = f"""
4
+ Today is {datetime.datetime.now()}
5
+
6
+ You are Emilia and you assist Peter
7
+
8
+ You have several tools to facilitate your assisting process:
9
+
10
+ 1. search_internet
11
+ 2. what_time_is_it
12
+
13
+ 1. Use this tool when Peter needs up-to-date accurate information about something, you have to generate a single search request based on Peter's initial question, then, pass the search request to "search_internet" and wait for the results.
14
+
15
+ After getting the results, you provide Peter with a detailed message explaining what you got.
16
+
17
+ 2. Use tool whenever you or Peter needs to know what time it is right in the moment.
18
+ """
@@ -0,0 +1,11 @@
1
+ from emilia.emilia import Emilia
2
+ import sys
3
+
4
+ def main() -> int:
5
+ emilia = Emilia("qwen3")
6
+ emilia.talk()
7
+
8
+ return 0
9
+
10
+ if __name__ == "__main__":
11
+ sys.exit(main())
@@ -0,0 +1,87 @@
1
+ from ddgs import DDGS
2
+ from ddgs.exceptions import DDGSException
3
+ from trafilatura import (
4
+ fetch_url,
5
+ extract,
6
+ )
7
+
8
+ from kopilogs.paint import paint
9
+
10
+ from concurrent.futures import ThreadPoolExecutor
11
+ import sys
12
+ import textwrap
13
+ import datetime
14
+
15
+ def what_time_is_it() -> str:
16
+ """
17
+ Use this tool whenever you want to know what time it is right now.
18
+
19
+ Args:
20
+ None
21
+
22
+ Returns:
23
+ str -> Formatted string containing the exact datetime
24
+ """
25
+ paint(f"Getting datetime...").bold().magenta().show()
26
+
27
+ return datetime.datetime.now().strftime(r"%Y/%m/%d -- %H:%M:%S")
28
+
29
+ def search_internet(search_query: str) -> str:
30
+ """
31
+ Use this tool when Peter need up-to-date accurate facts about something.
32
+
33
+ Args:
34
+ str -> Search query
35
+
36
+ Returns:
37
+ str -> Formatted str containing webpages: [title, href, information]
38
+
39
+ Use the information retrieved to answer Peter
40
+ """
41
+ paint(f"Searching the internet... {search_query}").bold().magenta().show()
42
+
43
+ def fetch(result: dict[str, str]) -> str | None:
44
+ extracted = extract(fetch_url(result["href"]))
45
+ return extracted
46
+
47
+ results = list(DDGS().text(search_query, max_results=3))
48
+ with ThreadPoolExecutor() as exec:
49
+ threads = []
50
+
51
+ for result in results:
52
+ thread = exec.submit(fetch, result)
53
+ threads.append(thread)
54
+
55
+ formatted_results = ""
56
+ for i, thread in enumerate(threads):
57
+ try:
58
+ result = thread.result()
59
+ except Exception:
60
+ continue
61
+
62
+ if result is not None:
63
+ formatted_results += textwrap.dedent(
64
+ f"""
65
+
66
+ RESULT {i}
67
+
68
+ {result[:5000]}
69
+
70
+ """
71
+ )
72
+
73
+ paint("Done.").bold().green().show()
74
+ return formatted_results
75
+
76
+ def testing() -> None:
77
+ """
78
+ This is a testing tool, only execute this when commanded
79
+
80
+ Args:
81
+ None
82
+
83
+ Returns:
84
+ None
85
+ """
86
+
87
+ print("Executed testing tool!")
@@ -0,0 +1,3 @@
1
+ import datetime
2
+
3
+ print(datetime.datetime.now())