xgae 0.1.2__py3-none-any.whl → 0.1.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.

Potentially problematic release.


This version of xgae might be problematic. Click here for more details.

xgae/engine/xga_base.py CHANGED
@@ -2,7 +2,9 @@ from typing import Union, Optional, Dict, List, Any, Literal
2
2
  from dataclasses import dataclass
3
3
  from abc import ABC, abstractmethod
4
4
 
5
-
5
+ class XGAError(Exception):
6
+ """Custom exception for errors in the XGA system."""
7
+ pass
6
8
 
7
9
  @dataclass
8
10
  class XGAMessage:
xgae/engine/xga_engine.py CHANGED
@@ -2,68 +2,74 @@
2
2
  from typing import List, Any, Dict, Optional, AsyncGenerator
3
3
  from uuid import uuid4
4
4
 
5
- from xgae.engine.xga_base import XGAMessage, XGAToolSchema, XGAToolBox
5
+ from xgae.engine.xga_base import XGAMessage, XGAToolBox
6
6
  from xgae.utils.llm_client import LLMClient
7
7
  from xgae.utils.setup_env import langfuse
8
8
  from xga_prompt_builder import XGAPromptBuilder
9
9
  from xga_mcp_tool_box import XGAMcpToolBox
10
10
 
11
11
 
12
- class XGAEngine():
12
+ class XGATaskEngine():
13
13
  def __init__(self,
14
14
  session_id: Optional[str] = None,
15
- trace_id: Optional[str] = None,
15
+ task_id: Optional[str] = None,
16
16
  agent_id: Optional[str] = None,
17
+ trace_id: Optional[str] = None,
18
+ system_prompt: Optional[str] = None,
17
19
  llm_config: Optional[Dict[str, Any]] = None,
18
20
  prompt_builder: Optional[XGAPromptBuilder] = None,
19
21
  tool_box: Optional[XGAToolBox] = None):
20
22
  self.session_id = session_id if session_id else f"xga_sid_{uuid4()}"
23
+ self.task_id = task_id if task_id else f"xga_task_{uuid4()}"
21
24
  self.agent_id = agent_id
25
+ self.trace_id = trace_id if trace_id else langfuse.create_trace_id()
22
26
 
23
27
  self.messages: List[XGAMessage] = []
24
28
  self.llm_client = LLMClient(llm_config)
25
29
  self.model_name = self.llm_client.model_name
26
30
  self.is_stream = self.llm_client.is_stream
27
31
 
28
- self.prompt_builder = prompt_builder or XGAPromptBuilder()
32
+ self.prompt_builder = prompt_builder or XGAPromptBuilder(system_prompt)
29
33
  self.tool_box = tool_box or XGAMcpToolBox()
30
34
 
31
- self.task_id = None
32
- self.trace_id = trace_id if trace_id else langfuse.create_trace_id()
33
35
 
34
- async def __async_init__(self) -> None:
36
+ async def __async_init__(self, general_tools:List[str], custom_tools: List[str]) -> None:
35
37
  await self.tool_box.load_mcp_tools_schema()
38
+ await self.tool_box.creat_task_tool_box(self.task_id, general_tools, custom_tools)
39
+ general_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "general_tool")
40
+ custom_tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "custom_tool")
41
+
42
+ self.task_prompt = self.prompt_builder.build_task_prompt(self.model_name, general_tool_schemas, custom_tool_schemas)
36
43
 
37
44
  @classmethod
38
45
  async def create(cls,
39
46
  session_id: Optional[str] = None,
40
- trace_id: Optional[str] = None,
47
+ task_id: Optional[str] = None,
41
48
  agent_id: Optional[str] = None,
49
+ trace_id: Optional[str] = None,
50
+ system_prompt: Optional[str] = None,
51
+ general_tools: Optional[List[str]] = None,
52
+ custom_tools: Optional[List[str]] = None,
42
53
  llm_config: Optional[Dict[str, Any]] = None,
43
54
  prompt_builder: Optional[XGAPromptBuilder] = None,
44
- tool_box: Optional[XGAToolBox] = None) -> 'XGAEngine' :
45
- engine: XGAEngine = cls(session_id=session_id,
46
- trace_id=trace_id,
47
- agent_id=agent_id,
48
- llm_config=llm_config,
49
- prompt_builder=prompt_builder,
50
- tool_box=tool_box)
51
-
52
- await engine.__async_init__()
55
+ tool_box: Optional[XGAToolBox] = None) -> 'XGATaskEngine':
56
+ engine: XGATaskEngine = cls(session_id=session_id,
57
+ task_id=task_id,
58
+ agent_id=agent_id,
59
+ trace_id=trace_id,
60
+ system_prompt=system_prompt,
61
+ llm_config=llm_config,
62
+ prompt_builder=prompt_builder,
63
+ tool_box=tool_box)
64
+ general_tools = general_tools or ["*"]
65
+ custom_tools = custom_tools or []
66
+ await engine.__async_init__(general_tools, custom_tools)
53
67
  return engine
54
68
 
55
69
 
56
- async def run_task(self,
57
- task_messages: List[Dict[str, Any]],
58
- task_id: Optional[str] = None,
59
- system_prompt: Optional[str] = None,
60
- general_tools: Optional[List[str]] = ["*"],
61
- custom_tools: Optional[List[str]] = []) -> AsyncGenerator:
70
+ async def run_task(self, task_messages: List[Dict[str, Any]]) -> AsyncGenerator:
62
71
  try:
63
- self.task_id = task_id if task_id else f"xga_task_{uuid4()}"
64
- await self.tool_box.creat_task_tool_box(self.task_id, general_tools, custom_tools)
65
- task_prompt = self.build_task_prompt(system_prompt)
66
- yield task_prompt
72
+ yield self.task_prompt
67
73
 
68
74
  finally:
69
75
  await self.tool_box.destroy_task_tool_box(self.task_id)
@@ -72,18 +78,6 @@ class XGAEngine():
72
78
  def _run_task_once(self):
73
79
  pass
74
80
 
75
- def build_task_prompt(self, system_prompt: Optional[str] = None) -> str:
76
- task_prompt = self.prompt_builder.build_system_prompt(self.model_name, system_prompt)
77
-
78
- tool_schemas =self.tool_box.get_task_tool_schemas(self.task_id, "general_tool")
79
- tool_prompt = self.prompt_builder.build_general_tool_prompt(tool_schemas)
80
- task_prompt = task_prompt + "\n" + tool_prompt
81
-
82
- tool_schemas = self.tool_box.get_task_tool_schemas(self.task_id, "custom_tool")
83
- tool_prompt = self.prompt_builder.build_custom_tool_prompt(tool_schemas)
84
- task_prompt = task_prompt + "\n" + tool_prompt
85
-
86
- return task_prompt
87
81
 
88
82
  def add_message(self, message: XGAMessage):
89
83
  message.message_id = f"xga_msg_{uuid4()}"
@@ -95,11 +89,11 @@ if __name__ == "__main__":
95
89
  import asyncio
96
90
 
97
91
  async def main():
98
- #tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
99
- tool_box = None
100
- engine = await XGAEngine.create(tool_box=tool_box)
101
- # async for chunk in engine.run_task(task_messages=[{}], custom_tools=["bomc_fault.*"]):
102
- async for chunk in engine.run_task(task_messages=[{}], custom_tools=[]):
92
+ tool_box = XGAMcpToolBox(custom_mcp_server_file="mcpservers/custom_servers.json")
93
+ engine = await XGATaskEngine.create(tool_box=tool_box, custom_tools=["bomc_fault.*"])
94
+ # engine = await XGATaskEngine.create()
95
+
96
+ async for chunk in engine.run_task(task_messages=[{}]):
103
97
  print(chunk)
104
98
 
105
99
  asyncio.run(main())
@@ -7,9 +7,8 @@ from typing import List, Any, Dict, Optional, Literal, override
7
7
  from langchain_mcp_adapters.client import MultiServerMCPClient
8
8
  from langchain_mcp_adapters.tools import load_mcp_tools
9
9
 
10
- from xgae.engine.xga_base import XGAToolSchema, XGAToolBox, XGAToolResult
11
- from xgae.utils.setup_env import XGAError
12
-
10
+ from xgae.engine.xga_base import XGAError, XGAToolSchema, XGAToolBox, XGAToolResult
11
+ from xgae.utils.setup_env import langfuse
13
12
 
14
13
  class XGAMcpToolBox(XGAToolBox):
15
14
  GENERAL_MCP_SERVER_NAME = "xga_general"
@@ -1,25 +1,28 @@
1
- import datetime
2
- import sys
3
1
  import json
4
-
2
+ import datetime
5
3
  from typing import Optional, List
6
- from io import StringIO
7
4
 
8
- from xga_base import XGAToolSchema
9
- from xgae.utils.setup_env import read_file, XGAError
5
+ from xga_base import XGAToolSchema, XGAError
6
+ from xgae.utils.utils import read_file, format_file_with_args
10
7
 
11
8
 
12
9
  class XGAPromptBuilder():
13
- def __init__(self, system_prompt_template: Optional[str] = None):
14
- self.system_prompt = None
15
- if system_prompt_template:
16
- self.system_prompt = system_prompt_template
10
+ def __init__(self, system_prompt: Optional[str] = None):
11
+ self.system_prompt = system_prompt
12
+
13
+ def build_task_prompt(self, model_name: str, general_tool_schemas: List[XGAToolSchema], custom_tool_schemas: List[XGAToolSchema])-> str:
14
+ if self.system_prompt is None:
15
+ self.system_prompt = self._load_default_system_prompt(model_name)
16
+
17
+ task_prompt = self.system_prompt
18
+
19
+ tool_prompt = self.build_general_tool_prompt(general_tool_schemas)
20
+ task_prompt = task_prompt + "\n" + tool_prompt
21
+
22
+ tool_prompt = self.build_custom_tool_prompt(custom_tool_schemas)
23
+ task_prompt = task_prompt + "\n" + tool_prompt
17
24
 
18
- def build_system_prompt(self, model_name: str, system_prompt: Optional[str]=None)-> str:
19
- task_system_prompt = system_prompt if system_prompt else self.system_prompt
20
- if task_system_prompt is None:
21
- task_system_prompt = self._load_default_system_prompt(model_name)
22
- return task_system_prompt
25
+ return task_prompt
23
26
 
24
27
  def build_general_tool_prompt(self, tool_schemas:List[XGAToolSchema])-> str:
25
28
  tool_prompt = ""
@@ -41,7 +44,7 @@ class XGAPromptBuilder():
41
44
  input_schema = tool_schema.input_schema
42
45
  openai_function["parameters"] = openai_parameters
43
46
  openai_parameters["type"] = input_schema["type"]
44
- openai_parameters["properties"] = input_schema.get("properties", [])
47
+ openai_parameters["properties"] = input_schema.get("properties", {})
45
48
  openai_parameters["required"] = input_schema["required"]
46
49
 
47
50
  openai_schemas.append(openai_schema)
@@ -65,32 +68,21 @@ class XGAPromptBuilder():
65
68
  for tool_schema in tool_schemas:
66
69
  description = tool_schema.description if tool_schema.description else 'No description available'
67
70
  tool_info += f"- **{tool_schema.tool_name}**: {description}\n"
68
- tool_info += f" Parameters: {tool_schema.input_schema}\n"
71
+ parameters = tool_schema.input_schema.get("properties", {})
72
+ tool_info += f" Parameters: {parameters}\n"
69
73
  tool_prompt = tool_prompt.replace("{tool_schemas}", tool_info)
70
74
 
71
75
  return tool_prompt
72
76
 
73
77
  def _load_default_system_prompt(self, model_name) -> Optional[str]:
74
78
  if "gemini-2.5-flash" in model_name.lower() and "gemini-2.5-pro" not in model_name.lower():
75
- org_prompt_template = read_file("templates/gemini_system_prompt_template.txt")
79
+ system_prompt_template = read_file("templates/gemini_system_prompt_template.txt")
76
80
  else:
77
- org_prompt_template = read_file("templates/system_prompt_template.txt")
78
-
79
- original_stdout = sys.stdout
80
- buffer = StringIO()
81
- sys.stdout = buffer
82
- try:
83
- namespace = {
84
- "datetime": datetime,
85
- "__builtins__": __builtins__
86
- }
87
- code = f"print(f\"\"\"{org_prompt_template}\"\"\")"
88
- exec(code, namespace)
89
- system_prompt_template = buffer.getvalue()
90
- finally:
91
- sys.stdout = original_stdout
92
-
93
- system_prompt = system_prompt_template.format(
81
+ system_prompt_template = read_file("templates/system_prompt_template.txt")
82
+
83
+ system_prompt = format_file_with_args(system_prompt_template, {"datetime": datetime})
84
+
85
+ system_prompt = system_prompt.format(
94
86
  current_date=datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d'),
95
87
  current_time=datetime.datetime.now(datetime.timezone.utc).strftime('%H:%M:%S'),
96
88
  current_year=datetime.datetime.now(datetime.timezone.utc).strftime('%Y')
@@ -102,14 +94,4 @@ class XGAPromptBuilder():
102
94
 
103
95
  return system_prompt
104
96
 
105
- if __name__ == "__main__":
106
-
107
- prompt_builder = XGAPromptBuilder()
108
- prompt = prompt_builder.build_system_prompt("openai/qwen3-235b-a22b")
109
-
110
- # system_prompt = read_file("templates/scp_test_prompt.txt")
111
- # prompt = prompt_builder.build_system_prompt("openai/qwen3-235b-a22b", system_prompt=system_prompt)
112
-
113
- print(prompt)
114
-
115
97
 
xgae/utils/setup_env.py CHANGED
@@ -1,10 +1,8 @@
1
1
  import logging
2
2
  import os
3
- import traceback
4
3
 
5
4
  from langfuse import Langfuse
6
5
 
7
-
8
6
  _log_initialized = False
9
7
 
10
8
  def setup_logging() -> None:
@@ -65,17 +63,6 @@ def setup_logging() -> None:
65
63
 
66
64
  setup_logging()
67
65
 
68
-
69
- class XGAError(Exception):
70
- """Custom exception for errors in the XGA system."""
71
- pass
72
-
73
- def handle_error(e: Exception) -> None:
74
- logging.error("An error occurred: %s", str(e))
75
- logging.error("Traceback details:\n%s", traceback.format_exc())
76
- raise (e) from e
77
-
78
-
79
66
  _langfuse_initialized = False
80
67
 
81
68
  def setup_langfuse() -> Langfuse:
@@ -101,20 +88,6 @@ def setup_langfuse() -> Langfuse:
101
88
  langfuse: Langfuse = Langfuse if _langfuse_initialized else setup_langfuse()
102
89
 
103
90
 
104
- def read_file(file_path: str) -> str:
105
- if not os.path.exists(file_path):
106
- logging.error(f"File '{file_path}' not found")
107
- raise XGAError(f"File '{file_path}' not found")
108
-
109
- try:
110
- with open(file_path, "r", encoding="utf-8") as template_file:
111
- content = template_file.read()
112
- return content
113
- except Exception as e:
114
- logging.error(f"Read file '{file_path}' failed")
115
- handle_error(e)
116
-
117
-
118
91
  if __name__ == "__main__":
119
92
  try:
120
93
  trace_id = langfuse.create_trace_id()
xgae/utils/utils.py ADDED
@@ -0,0 +1,42 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ import datetime
5
+
6
+ from typing import Any, Dict
7
+
8
+ def handle_error(e: Exception) -> None:
9
+ import traceback
10
+
11
+ logging.error("An error occurred: %s", str(e))
12
+ logging.error("Traceback details:\n%s", traceback.format_exc())
13
+ raise (e) from e
14
+
15
+ def read_file(file_path: str) -> str:
16
+ if not os.path.exists(file_path):
17
+ logging.error(f"File '{file_path}' not found")
18
+ raise Exception(f"File '{file_path}' not found")
19
+
20
+ try:
21
+ with open(file_path, "r", encoding="utf-8") as template_file:
22
+ content = template_file.read()
23
+ return content
24
+ except Exception as e:
25
+ logging.error(f"Read file '{file_path}' failed")
26
+ handle_error(e)
27
+
28
+ def format_file_with_args(file_content:str, args: Dict[str, Any])-> str:
29
+ from io import StringIO
30
+
31
+ formated = file_content
32
+ original_stdout = sys.stdout
33
+ buffer = StringIO()
34
+ sys.stdout = buffer
35
+ try:
36
+ code = f"print(f\"\"\"{file_content}\"\"\")"
37
+ exec(code, args)
38
+ formated = buffer.getvalue()
39
+ finally:
40
+ sys.stdout = original_stdout
41
+
42
+ return formated
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xgae
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Extreme General Agent Engine
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: colorlog>=6.9.0
@@ -0,0 +1,14 @@
1
+ xgae/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ xgae/engine/xga_base.py,sha256=b9FnBbCuO4lCAIBBhnedtRk49Dl3M6cBn5h_Wkzw4o0,1345
3
+ xgae/engine/xga_engine.py,sha256=kci7pvF8NwAYJ3Y6DS0JKLkPEQERZwcwRzjcAFQx_ec,4169
4
+ xgae/engine/xga_mcp_tool_box.py,sha256=coyQy7tj2YTBpOc0JKmVBJO8ItO4Z6s1pdbucHd85qg,9762
5
+ xgae/engine/xga_prompt_builder.py,sha256=RuTvQCNufqxDwVvSOPXR0qxAc42cG7NuIaUy9amu66A,4351
6
+ xgae/engine/responser/xga_non_stream_responser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ xgae/engine/responser/xga_responser_utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ xgae/engine/responser/xga_stream_reponser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ xgae/utils/llm_client.py,sha256=UMMK84psLsx36-Nn6Q8X1hl9wd-OdaS9ZhxbRjwNCr0,12149
10
+ xgae/utils/setup_env.py,sha256=vY2wnq5KMXQ2dx2wAPeTpudp7b-fvgzenkwHpgd8vuI,2951
11
+ xgae/utils/utils.py,sha256=cCYmWjKFksZ8BRD1YYnaM_jTLVHAg1ibEdjsczEUO6k,1134
12
+ xgae-0.1.3.dist-info/METADATA,sha256=t4sr4k9pbVAcicIRjoqt327eWtSC0uAeo2pDB5LPjs0,309
13
+ xgae-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ xgae-0.1.3.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- xgae/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- xgae/engine/xga_base.py,sha256=vOiYWoBze7VrmndYnaNhMzoB1zCT80WtIlOWdp2IrUc,1253
3
- xgae/engine/xga_engine.py,sha256=AgklNAimyErvn74xUu6aardZvgjqbIR99gCojEmZfO0,4267
4
- xgae/engine/xga_mcp_tool_box.py,sha256=jRYvZ8eY72KRU0leD-o15fe_E8wjWJtxQZbsIqGVjPU,9753
5
- xgae/engine/xga_prompt_builder.py,sha256=Q3nrmYAofRkFQFdfSWkP00FZKjWMUQs2cvMs7bvyQgQ,4819
6
- xgae/engine/responser/xga_non_stream_responser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- xgae/engine/responser/xga_responser_utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- xgae/engine/responser/xga_stream_reponser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- xgae/utils/llm_client.py,sha256=UMMK84psLsx36-Nn6Q8X1hl9wd-OdaS9ZhxbRjwNCr0,12149
10
- xgae/utils/setup_env.py,sha256=qZmVfqaYHtjq5t-zwRt_G3i-QqGPxSb4D2FnFHbhdcY,3689
11
- xgae-0.1.2.dist-info/METADATA,sha256=iBwWKlpbp7z0ZQgydnieP_2NBf0Z7H0D6AtavbIN3Zc,309
12
- xgae-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- xgae-0.1.2.dist-info/RECORD,,
File without changes