lionagi 0.0.114__py3-none-any.whl → 0.0.116__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.
Files changed (99) hide show
  1. lionagi/__init__.py +7 -4
  2. lionagi/bridge/__init__.py +19 -4
  3. lionagi/bridge/langchain.py +23 -3
  4. lionagi/bridge/llama_index.py +5 -3
  5. lionagi/configs/__init__.py +1 -1
  6. lionagi/configs/oai_configs.py +88 -1
  7. lionagi/core/__init__.py +6 -9
  8. lionagi/core/conversations/__init__.py +5 -0
  9. lionagi/core/conversations/conversation.py +107 -0
  10. lionagi/core/flows/__init__.py +8 -0
  11. lionagi/core/flows/flow.py +8 -0
  12. lionagi/core/flows/flow_util.py +62 -0
  13. lionagi/core/instruction_set/__init__.py +5 -0
  14. lionagi/core/instruction_set/instruction_sets.py +7 -0
  15. lionagi/core/sessions/__init__.py +5 -0
  16. lionagi/core/sessions/sessions.py +187 -0
  17. lionagi/endpoints/__init__.py +5 -0
  18. lionagi/endpoints/assistants.py +0 -0
  19. lionagi/endpoints/audio.py +17 -0
  20. lionagi/endpoints/chatcompletion.py +54 -0
  21. lionagi/endpoints/embeddings.py +0 -0
  22. lionagi/endpoints/finetune.py +0 -0
  23. lionagi/endpoints/image.py +0 -0
  24. lionagi/endpoints/moderation.py +0 -0
  25. lionagi/endpoints/vision.py +0 -0
  26. lionagi/{loader → loaders}/__init__.py +7 -1
  27. lionagi/{loader → loaders}/chunker.py +6 -12
  28. lionagi/{utils/load_utils.py → loaders/load_util.py} +47 -6
  29. lionagi/{loader → loaders}/reader.py +4 -12
  30. lionagi/messages/__init__.py +11 -0
  31. lionagi/messages/instruction.py +15 -0
  32. lionagi/messages/message.py +110 -0
  33. lionagi/messages/response.py +33 -0
  34. lionagi/messages/system.py +12 -0
  35. lionagi/objs/__init__.py +10 -6
  36. lionagi/objs/abc_objs.py +39 -0
  37. lionagi/objs/async_queue.py +135 -0
  38. lionagi/objs/messenger.py +70 -148
  39. lionagi/objs/status_tracker.py +37 -0
  40. lionagi/objs/{tool_registry.py → tool_manager.py} +8 -6
  41. lionagi/schema/__init__.py +3 -3
  42. lionagi/schema/base_node.py +251 -0
  43. lionagi/schema/base_tool.py +8 -3
  44. lionagi/schema/data_logger.py +2 -3
  45. lionagi/schema/data_node.py +37 -0
  46. lionagi/services/__init__.py +1 -4
  47. lionagi/services/base_api_service.py +15 -5
  48. lionagi/services/oai.py +2 -2
  49. lionagi/services/openrouter.py +2 -3
  50. lionagi/structures/graph.py +96 -0
  51. lionagi/{structure → structures}/relationship.py +10 -2
  52. lionagi/structures/structure.py +102 -0
  53. lionagi/tests/test_api_util.py +46 -0
  54. lionagi/tests/test_call_util.py +115 -0
  55. lionagi/tests/test_convert_util.py +202 -0
  56. lionagi/tests/test_encrypt_util.py +33 -0
  57. lionagi/tests/{test_flatten_util.py → test_flat_util.py} +1 -1
  58. lionagi/tests/test_io_util.py +0 -0
  59. lionagi/tests/test_sys_util.py +0 -0
  60. lionagi/tools/__init__.py +5 -0
  61. lionagi/tools/tool_util.py +7 -0
  62. lionagi/utils/__init__.py +55 -35
  63. lionagi/utils/api_util.py +19 -17
  64. lionagi/utils/call_util.py +2 -1
  65. lionagi/utils/convert_util.py +229 -0
  66. lionagi/utils/encrypt_util.py +16 -0
  67. lionagi/utils/flat_util.py +38 -0
  68. lionagi/utils/io_util.py +2 -2
  69. lionagi/utils/sys_util.py +45 -10
  70. lionagi/version.py +1 -1
  71. {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/METADATA +2 -2
  72. lionagi-0.0.116.dist-info/RECORD +110 -0
  73. lionagi/core/conversations.py +0 -108
  74. lionagi/core/flows.py +0 -1
  75. lionagi/core/instruction_sets.py +0 -1
  76. lionagi/core/messages.py +0 -166
  77. lionagi/core/sessions.py +0 -297
  78. lionagi/schema/base_schema.py +0 -252
  79. lionagi/services/chatcompletion.py +0 -48
  80. lionagi/services/service_objs.py +0 -282
  81. lionagi/structure/structure.py +0 -160
  82. lionagi/tools/coder.py +0 -1
  83. lionagi/tools/sandbox.py +0 -1
  84. lionagi/utils/tool_util.py +0 -92
  85. lionagi/utils/type_util.py +0 -81
  86. lionagi-0.0.114.dist-info/RECORD +0 -84
  87. /lionagi/configs/{openrouter_config.py → openrouter_configs.py} +0 -0
  88. /lionagi/{datastore → datastores}/__init__.py +0 -0
  89. /lionagi/{datastore → datastores}/chroma.py +0 -0
  90. /lionagi/{datastore → datastores}/deeplake.py +0 -0
  91. /lionagi/{datastore → datastores}/elasticsearch.py +0 -0
  92. /lionagi/{datastore → datastores}/lantern.py +0 -0
  93. /lionagi/{datastore → datastores}/pinecone.py +0 -0
  94. /lionagi/{datastore → datastores}/postgres.py +0 -0
  95. /lionagi/{datastore → datastores}/qdrant.py +0 -0
  96. /lionagi/{structure → structures}/__init__.py +0 -0
  97. {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/LICENSE +0 -0
  98. {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/WHEEL +0 -0
  99. {lionagi-0.0.114.dist-info → lionagi-0.0.116.dist-info}/top_level.txt +0 -0
lionagi/__init__.py CHANGED
@@ -17,13 +17,16 @@ Copyright 2023 HaiyangLi <ocean@lionagi.ai>
17
17
  import logging
18
18
  from .version import __version__
19
19
 
20
+
20
21
  from .utils import *
21
22
  from .schema import *
22
- from .structure import *
23
- from .core import *
23
+ from .structures import *
24
+ from .loaders import *
25
+ from .messages import *
24
26
  from .objs import *
25
- # from .datastore import *
26
- # from .structure import *
27
+ from .tools import *
28
+ from .core import *
29
+
27
30
 
28
31
 
29
32
  logger = logging.getLogger(__name__)
@@ -1,7 +1,22 @@
1
- from .langchain import from_langchain
2
- from .llama_index import from_llama_index
1
+ from .langchain import(
2
+ from_langchain, to_langchain_document, langchain_loader,
3
+ langchain_loader, langchain_text_splitter
4
+ )
5
+
6
+ from .llama_index import (
7
+ from_llama_index, to_llama_index_textnode, get_llama_reader,
8
+ llama_index_reader, get_llama_parser, llama_index_node_parser
9
+ )
3
10
 
4
11
  __all__ = [
5
- "from_langchain",
6
- "from_llama_index"
12
+ 'from_langchain',
13
+ 'to_langchain_document',
14
+ 'langchain_loader',
15
+ 'from_llama_index',
16
+ 'to_llama_index_textnode',
17
+ 'get_llama_reader',
18
+ 'llama_index_reader',
19
+ 'get_llama_parser',
20
+ 'llama_index_node_parser',
21
+ 'langchain_text_splitter'
7
22
  ]
@@ -1,7 +1,8 @@
1
- from typing import Union, Callable, List, Dict, Any
2
- from ..schema.base_schema import T, DataNode
3
- from ..utils.sys_util import change_dict_key
1
+ from typing import Union, Callable, List, Dict, Any, TypeVar
2
+ from lionagi.schema.data_node import DataNode
3
+ from lionagi.utils.sys_util import change_dict_key
4
4
 
5
+ T = TypeVar('T', bound='DataNode')
5
6
 
6
7
  def from_langchain(lc_doc: Any) -> T:
7
8
  """
@@ -79,6 +80,25 @@ def langchain_text_splitter(data: Union[str, List],
79
80
  splitter_args: List[Any] = [],
80
81
  splitter_kwargs: Dict[str, Any] = {}) -> List[str]:
81
82
 
83
+ """
84
+ Splits text or a list of documents using a specified langchain text splitter.
85
+
86
+ Parameters:
87
+ data (Union[str, List]): The input text or list of documents to be split.
88
+
89
+ splitter (Union[str, Callable]): The name of the text splitter function or the function itself.
90
+
91
+ splitter_args (List[Any]): Positional arguments to pass to the splitter function.
92
+
93
+ splitter_kwargs (Dict[str, Any]): Keyword arguments to pass to the splitter function.
94
+
95
+ Returns:
96
+ List[str]: A list of chunks obtained by splitting the input.
97
+
98
+ Raises:
99
+ ValueError: If the specified text splitter is invalid or if the splitting fails.
100
+ """
101
+
82
102
  import langchain.text_splitter as text_splitter
83
103
 
84
104
  try:
@@ -1,7 +1,8 @@
1
- from typing import Union, Callable, List, Any, Dict
2
- from ..schema.base_schema import DataNode, T
3
- from ..utils.sys_util import change_dict_key
1
+ from typing import Union, Callable, List, Any, Dict, TypeVar
2
+ from lionagi.schema.data_node import DataNode
3
+ from lionagi.utils.sys_util import change_dict_key
4
4
 
5
+ T = TypeVar('T', bound='DataNode')
5
6
 
6
7
  def from_llama_index(llama_node: Any, **kwargs: Any) -> T:
7
8
  """
@@ -36,6 +37,7 @@ def to_llama_index_textnode(datanode: T, **kwargs: Any) -> Any:
36
37
  dnode = datanode.to_dict()
37
38
  change_dict_key(dnode, old_key='content', new_key='text')
38
39
  change_dict_key(dnode, old_key='node_id', new_key='id_')
40
+ dnode['text'] = str(dnode['text'])
39
41
 
40
42
  dnode = {**dnode, **kwargs}
41
43
  return TextNode.from_dict(dnode)
@@ -1,5 +1,5 @@
1
1
  from .oai_configs import oai_schema
2
- from .openrouter_config import openrouter_schema
2
+ from .openrouter_configs import openrouter_schema
3
3
 
4
4
  __all__ = [
5
5
  "oai_schema",
@@ -1,3 +1,6 @@
1
+ # Default configs for the OpenAI API
2
+
3
+ # ChatCompletion
1
4
  oai_chat_llmconfig = {
2
5
  "model": "gpt-4-1106-preview",
3
6
  "frequency_penalty": 0,
@@ -22,6 +25,8 @@ oai_chat_schema = {
22
25
  "config": oai_chat_llmconfig
23
26
  }
24
27
 
28
+
29
+ # Finetune
25
30
  oai_finetune_llmconfig = {
26
31
  "model": "gpt-3.5-turbo",
27
32
  "hyperparameters": {
@@ -41,9 +46,91 @@ oai_finetune_schema = {
41
46
  }
42
47
 
43
48
 
49
+
50
+ # Embeddings
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+ # Audio ---- create speech
62
+
63
+ oai_audio_speech_llmconfig = {
64
+ "model": "tts-1",
65
+ "voice": "alloy",
66
+ "response_format": "mp3",
67
+ "speed": 1
68
+ }
69
+ oai_audio_speech_schema = {
70
+ "required" : ["model", "voice"],
71
+ "optional": ["response_format", "speed"],
72
+ "input": "input",
73
+ "config": oai_audio_speech_llmconfig
74
+ }
75
+
76
+
77
+ # Audio ----------- create transcription
78
+ oai_audio_transcriptions_llmconfig = {
79
+ "model": "whisper-1",
80
+ "language": None,
81
+ "prompt": None,
82
+ "response_format": "json",
83
+ "temperature": 0
84
+ }
85
+ oai_audio_transcriptions_schema = {
86
+ "required" : ["model", "voice"],
87
+ "optional": ["response_format", "language", "prompt", "response_format", "temperature"],
88
+ "input": "file",
89
+ "config": oai_audio_transcriptions_llmconfig
90
+ }
91
+
92
+
93
+ # Audio ------------ translations
94
+ oai_audio_translations_llmconfig = {
95
+ "model": "whisper-1",
96
+ "prompt": None,
97
+ "response_format": "json",
98
+ "temperature": 0
99
+ }
100
+
101
+ oai_audio_translations_schema = {
102
+ "required" : ["model"],
103
+ "optional": ["response_format", "speed", "prompt", "temperature"],
104
+ "input": "file",
105
+ "config": oai_audio_translations_llmconfig
106
+ }
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+ # images
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
44
128
  oai_schema = {
45
129
 
46
130
  "chat": oai_chat_schema,
47
- "finetune": oai_finetune_schema
131
+ "finetune": oai_finetune_schema,
132
+ "audio_speech": oai_audio_speech_schema,
133
+ "audio_transcriptions": oai_audio_transcriptions_schema,
134
+ "audio_translations": oai_audio_translations_schema,
48
135
 
49
136
  }
lionagi/core/__init__.py CHANGED
@@ -1,15 +1,12 @@
1
- # from .messages import Response, Instruction, System
1
+ # from .instruction_set import InstructionSet
2
2
  from .conversations import Conversation
3
3
  from .sessions import Session
4
+ from .flows import run_session #, Flow
4
5
 
5
- # from .instruction_sets import InstructionSet
6
- # from .flows.flow import Flow
7
6
 
8
-
9
- __all__ = [
10
- # "Response",
11
- # "Instruction",
12
- # "System",
7
+ __all__ = [
13
8
  "Conversation",
14
- "Session", #"Flow", "InstructionSet"
9
+ "Session",
10
+ "run_session",
11
+ # "Flow"
15
12
  ]
@@ -0,0 +1,5 @@
1
+ from .conversation import Conversation
2
+
3
+ __all__ = [
4
+ "Conversation"
5
+ ]
@@ -0,0 +1,107 @@
1
+ from typing import List, Any
2
+
3
+ from lionagi.schema.base_node import BaseNode
4
+ from lionagi.messages import Message, Response
5
+ from lionagi.objs.messenger import Messenger
6
+
7
+
8
+ class Conversation(BaseNode):
9
+ """
10
+ A conversation that handles messages and responses.
11
+
12
+ Attributes:
13
+ response_counts (int): A counter for the number of responses in the conversation.
14
+ messages (List[Message]): A list of message objects in the conversation.
15
+ msgr (Messenger): An instance of Messenger to create message objects.
16
+ responses (List[Response]): A list of response objects in the conversation.
17
+ """
18
+
19
+ response_counts : int = 0
20
+ messages: List[Message] = []
21
+ msgr : Any = Messenger()
22
+ responses: List[Response] = []
23
+
24
+ def initiate_conversation(
25
+ self, system=None, instruction=None,
26
+ context=None, name=None
27
+ ):
28
+ """
29
+ Initiates a new conversation, erase previous messages and responses.
30
+
31
+ Parameters:
32
+ system (Any, optional): System information to include in the initial message. Defaults to None.
33
+ instruction (Any, optional): Instruction details to include in the conversation. Defaults to None.
34
+ context (Any, optional): Contextual information relevant to the conversation. Defaults to None.
35
+ name (str, optional): The name associated with the conversation. Defaults to None.
36
+
37
+ Returns:
38
+ None
39
+ """
40
+ self.messages, self.responses = [], []
41
+ self.add_messages(system=system)
42
+ self.add_messages(instruction=instruction, context=context, name=name)
43
+
44
+ # modify the message adding to accomodate tools
45
+ def add_messages(
46
+ self, system=None, instruction=None,
47
+ context=None, response=None, name=None
48
+ ):
49
+ """
50
+ Adds a new message object to the conversation messages list based on the provided parameters.
51
+
52
+ Parameters:
53
+ system (Any, optional): System information to include in the message. Defaults to None.
54
+ instruction (Any, optional): Instruction details to include in the message. Defaults to None.
55
+ context (Any, optional): Contextual information relevant to the message. Defaults to None.
56
+ response (Any, optional): Response details to include in the message. Defaults to None.
57
+ name (str, optional): The name associated with the message. Defaults to None.
58
+
59
+ Returns:
60
+ None
61
+ """
62
+ msg = self.msgr.create_message(
63
+ system=system, instruction=instruction,
64
+ context=context, response=response, name=name
65
+ )
66
+ self.messages.append(msg)
67
+
68
+ def change_system(self, system):
69
+ """
70
+ Changes the system information of the first message in the conversation.
71
+
72
+ Parameters:
73
+ system (Any): The new system information to be set.
74
+
75
+ Returns:
76
+ None
77
+ """
78
+ self.messages[0] = self.msgr.create_message(system=system)
79
+
80
+
81
+ def keep_last_n_exchanges(self, n: int):
82
+ """
83
+ Keeps only the last n exchanges in the conversation, where an exchange starts with a user message. This function trims the conversation to retain only the specified number of the most recent exchanges.
84
+ An exchange is defined as a sequence of messages starting with a user message.
85
+ The first message in the conversation, typically a system message, is always retained.
86
+
87
+ Parameters:
88
+ n (int): The number of exchanges to keep in the conversation.
89
+
90
+ Returns:
91
+ None: The method modifies the conversation in place and does not return a value.
92
+
93
+ Raises:
94
+ ValueError: If n is not a positive integer.
95
+
96
+ Note:
97
+ This function assumes the first message in the conversation is a system message and each user message
98
+ marks the beginning of a new exchange.
99
+ """
100
+ response_indices = [
101
+ index for index, message in enumerate(self.messages[1:])
102
+ if message.role == "user"
103
+ ]
104
+ if len(response_indices) >= n:
105
+ first_index_to_keep = response_indices[-n] + 1
106
+ self.messages = [self.system] + self.messages[first_index_to_keep:]
107
+
@@ -0,0 +1,8 @@
1
+ from .flow_util import run_session
2
+ from .flow import Flow
3
+
4
+
5
+ __all__ = [
6
+ "run_session",
7
+ "Flow"
8
+ ]
@@ -0,0 +1,8 @@
1
+ from lionagi.structures import Relationship, Structure
2
+ from ..sessions import Session
3
+ from .flow_util import run_session
4
+
5
+ # represents structured sessions
6
+
7
+ class Flow(Structure):
8
+ ...
@@ -0,0 +1,62 @@
1
+ from ..sessions import Session
2
+
3
+ def get_config(temperature, max_tokens, key_scheme, n):
4
+ f = lambda i:{
5
+ "temperature": temperature[i],
6
+ "max_tokens": max_tokens[i],
7
+ }
8
+ return {
9
+ "key": f"{key_scheme}{n+1}",
10
+ "config": f(n)
11
+ }
12
+
13
+ async def run_workflow(
14
+ session, prompts, temperature, max_tokens,
15
+ key_scheme, num_prompts, context
16
+ ):
17
+ for i in range(num_prompts):
18
+ key_, config_ = get_config(temperature, max_tokens, key_scheme, i)
19
+ if i == 0:
20
+ await session.initiate(instruction=prompts[key_], context=context, **config_)
21
+ else:
22
+ await session.followup(instruction=prompts[key_], **config_)
23
+
24
+ return session
25
+
26
+ async def run_auto_workflow(
27
+ session, prompts, temperature, max_tokens,
28
+ key_scheme, num_prompts, context
29
+ ):
30
+ for i in range(num_prompts):
31
+ key_, config_ = get_config(temperature, max_tokens, key_scheme, i)
32
+ if i == 0:
33
+ await session.initiate(instruction=prompts[key_], context=context, **config_)
34
+ else:
35
+ await session.auto_followup(instruction=prompts[key_], **config_)
36
+
37
+ return session
38
+
39
+ async def run_session(
40
+ prompts, dir, llmconfig, key_scheme, num_prompts,
41
+ temperature, max_tokens, type_=None, tools=None
42
+ ):
43
+ prompts_ = prompts.copy()
44
+ session = Session(
45
+ system=prompts_.pop('system', 'You are a helpful assistant'),
46
+ dir = dir,
47
+ llmconfig = llmconfig
48
+ )
49
+ if tools:
50
+ session.register_tools(tools)
51
+ if type_ is None:
52
+ session = await run_workflow(
53
+ session, prompts_, temperature, max_tokens,
54
+ key_scheme=key_scheme, num_prompts=num_prompts
55
+ )
56
+ elif type_ == 'auto':
57
+ session = await run_auto_workflow(
58
+ session, prompts_, temperature, max_tokens,
59
+ key_scheme=key_scheme, num_prompts=num_prompts
60
+ )
61
+
62
+ return session
@@ -0,0 +1,5 @@
1
+ from .instruction_sets import InstructionSet
2
+
3
+ __all__ = [
4
+ "InstructionSet"
5
+ ]
@@ -0,0 +1,7 @@
1
+ from lionagi.structures import Relationship, Structure
2
+ from ..messages import Message, Instruction
3
+
4
+ # dynamically structured preconfigured instructions
5
+
6
+ class InstructionSet(Structure):
7
+ ...
@@ -0,0 +1,5 @@
1
+ from .sessions import Session
2
+
3
+ __all__ = [
4
+ "Session"
5
+ ]
@@ -0,0 +1,187 @@
1
+ import json
2
+ from typing import Any
3
+ from dotenv import load_dotenv
4
+
5
+ from lionagi.schema import DataLogger, Tool
6
+ from lionagi.utils import lcall, alcall
7
+ from lionagi.services import OpenAIService
8
+ from lionagi.endpoints import ChatCompletion
9
+ from lionagi.objs.tool_manager import ToolManager
10
+ from lionagi.configs.oai_configs import oai_schema
11
+ from lionagi.core.conversations.conversation import Conversation
12
+
13
+ load_dotenv()
14
+ OAIService = OpenAIService()
15
+
16
+
17
+ class Session:
18
+
19
+ def __init__(
20
+ self, system, dir=None, llmconfig=oai_schema['chat']['config'],
21
+ service=OAIService
22
+ ):
23
+ self.conversation = Conversation()
24
+ self.system = system
25
+ self.llmconfig = llmconfig
26
+ self.logger_ = DataLogger(dir=dir)
27
+ self.service = service
28
+ self.tool_manager = ToolManager()
29
+
30
+ def set_dir(self, dir):
31
+ self.logger_.dir = dir
32
+
33
+ def set_system(self, system):
34
+ self.conversation.change_system(system)
35
+
36
+ def set_llmconfig(self, llmconfig):
37
+ self.llmconfig = llmconfig
38
+
39
+ def set_service(self, service):
40
+ self.service = service
41
+
42
+ async def _output(self, invoke=True, out=True):
43
+ if invoke:
44
+ try:
45
+ # func, args = self.tool_manager._get_function_call(self.conversation.responses[-1]['content'])
46
+ # outs = await self.tool_manager.invoke(func, args)
47
+ # self.conversation.add_messages(response=outs)
48
+
49
+ tool_uses = json.loads(self.conversation.responses[-1].message_content)
50
+ if 'function_list' in tool_uses.keys():
51
+ func_calls = lcall(tool_uses['function_list'], self.tool_manager.get_function_call)
52
+ else:
53
+ func_calls = lcall(tool_uses['tool_uses'], self.tool_manager.get_function_call)
54
+
55
+ outs = await alcall(func_calls, self.tool_manager.invoke)
56
+ for out, f in zip(outs, func_calls):
57
+ response = {"function": f[0], "arguments": f[1], "output": out}
58
+ self.conversation.add_messages(response=response)
59
+ except:
60
+ pass
61
+ if out:
62
+ return self.conversation.responses[-1].message_content
63
+
64
+ def _is_invoked(self):
65
+ content = self.conversation.messages[-1].message_content
66
+ try:
67
+ if json.loads(content).keys() >= {'function', 'arguments', 'output'}:
68
+ return True
69
+ except:
70
+ return False
71
+
72
+ def register_tools(self, tools): #, update=False, new=False, prefix=None, postfix=None):
73
+ if not isinstance(tools, list):
74
+ tools=[tools]
75
+ self.tool_manager.register_tools(tools=tools) #, update=update, new=new, prefix=prefix, postfix=postfix)
76
+ # tools_schema = lcall(tools, lambda tool: tool.to_dict()['schema_'])
77
+ # if self.llmconfig['tools'] is None:
78
+ # self.llmconfig['tools'] = tools_schema
79
+ # else:
80
+ # self.llmconfig['tools'] += tools_schema
81
+
82
+ def _tool_parser(self, **kwargs):
83
+ # 1. single schema: dict
84
+ # 2. tool: Tool
85
+ # 3. name: str
86
+ # 4. list: 3 types of lists
87
+ def tool_check(tool):
88
+ if isinstance(tool, dict):
89
+ return tool
90
+ elif isinstance(tool, Tool):
91
+ return tool.schema_
92
+ elif isinstance(tool, str):
93
+ if self.tool_manager.name_existed(tool):
94
+ tool = self.tool_manager.registry[tool]
95
+ return tool.schema_
96
+ else:
97
+ raise ValueError(f'Function {tool} is not registered.')
98
+
99
+ if 'tools' in kwargs:
100
+ if not isinstance(kwargs['tools'], list):
101
+ kwargs['tools']=[kwargs['tools']]
102
+ kwargs['tools'] = lcall(kwargs['tools'], tool_check)
103
+
104
+ else:
105
+ tool_kwarg = {"tools": self.tool_manager.to_tool_schema_list()}
106
+ kwargs = {**tool_kwarg, **kwargs}
107
+
108
+ return kwargs
109
+
110
+ async def initiate(self, instruction, system=None, context=None,
111
+ name=None, invoke=True, out=True, **kwargs) -> Any:
112
+ # if self.tool_manager.registry != {}:
113
+ # if 'tools' not in kwargs:
114
+ # tool_kwarg = {"tools": self.tool_manager.to_tool_schema_list()}
115
+ # kwargs = {**tool_kwarg, **kwargs}
116
+ if self.tool_manager.registry != {}:
117
+ kwargs = self._tool_parser(**kwargs)
118
+ if self.service is not None:
119
+ await self.service._init()
120
+ config = {**self.llmconfig, **kwargs}
121
+ system = system or self.system
122
+ self.conversation.initiate_conversation(system=system, instruction=instruction, context=context, name=name)
123
+ await self.call_chatcompletion(**config)
124
+
125
+ return await self._output(invoke, out)
126
+
127
+ async def followup(self, instruction, system=None, context=None,
128
+ out=True, name=None, invoke=True, **kwargs) -> Any:
129
+ if system:
130
+ self.conversation.change_system(system)
131
+ self.conversation.add_messages(instruction=instruction, context=context, name=name)
132
+
133
+ if 'tool_parsed' in kwargs:
134
+ kwargs.pop('tool_parsed')
135
+ else:
136
+ if self.tool_manager.registry != {}:
137
+ kwargs = self._tool_parser(**kwargs)
138
+ # if self.tool_manager.registry != {}:
139
+ # if 'tools' not in kwargs:
140
+ # tool_kwarg = {"tools": self.tool_manager.to_tool_schema_list()}
141
+ # kwargs = {**tool_kwarg, **kwargs}
142
+ config = {**self.llmconfig, **kwargs}
143
+ await self.call_chatcompletion(**config)
144
+
145
+ return await self._output(invoke, out)
146
+
147
+ async def auto_followup(self, instruct, num=3, **kwargs):
148
+ # if self.tool_manager.registry != {}:
149
+ # if 'tools' not in kwargs:
150
+ # tool_kwarg = {"tools": self.tool_manager.to_tool_schema_list()}
151
+ # kwargs = {**tool_kwarg, **kwargs}
152
+ if self.tool_manager.registry != {}:
153
+ kwargs = self._tool_parser(**kwargs)
154
+
155
+ cont_ = True
156
+ while num > 0 and cont_ is True:
157
+ await self.followup(instruct, tool_choice="auto", tool_parsed=True, **kwargs)
158
+ num -= 1
159
+ cont_ = True if self._is_invoked() else False
160
+ if num == 0:
161
+ await self.followup(instruct, **kwargs, tool_parsed=True)
162
+
163
+ # def messages_to_csv(self, dir=None, filename="messages.csv", **kwargs):
164
+ # dir = dir or self.logger_.dir
165
+ # if dir is None:
166
+ # raise ValueError("No directory specified.")
167
+ # self.conversation.msg.to_csv(dir=dir, filename=filename, **kwargs)
168
+
169
+ # def log_to_csv(self, dir=None, filename="llmlog.csv", **kwargs):
170
+ # dir = dir or self.logger_.dir
171
+ # if dir is None:
172
+ # raise ValueError("No directory specified.")
173
+ # self.logger_.to_csv(dir=dir, filename=filename, **kwargs)
174
+
175
+ async def call_chatcompletion(self, schema=oai_schema['chat'], **kwargs):
176
+ messages = [message.message for message in self.conversation.messages]
177
+ payload = ChatCompletion.create_payload(messages=messages, schema=schema, llmconfig=self.llmconfig,**kwargs)
178
+ completion = await self.service.serve(payload=payload)
179
+ if "choices" in completion:
180
+ self.logger_({"input":payload, "output": completion})
181
+ self.conversation.add_messages(response=completion['choices'][0])
182
+ self.conversation.responses.append(self.conversation.messages[-1])
183
+ self.conversation.response_counts += 1
184
+ self.service.status_tracker.num_tasks_succeeded += 1
185
+ else:
186
+ self.service.status_tracker.num_tasks_failed += 1
187
+
@@ -0,0 +1,5 @@
1
+ from .chatcompletion import ChatCompletion
2
+
3
+ __all__ = [
4
+ "ChatCompletion",
5
+ ]
File without changes
@@ -0,0 +1,17 @@
1
+ # from .base_endpoint import BaseEndpoint
2
+
3
+
4
+ # class Audio(BaseEndpoint):
5
+ # endpoint: str = "chat/completions"
6
+
7
+ # @classmethod
8
+ # def create_payload(scls, messages, llmconfig, schema, **kwargs):
9
+ # config = {**llmconfig, **kwargs}
10
+ # payload = {"messages": messages}
11
+ # for key in schema['required']:
12
+ # payload.update({key: config[key]})
13
+
14
+ # for key in schema['optional']:
15
+ # if bool(config[key]) is True and str(config[key]).lower() != "none":
16
+ # payload.update({key: config[key]})
17
+ # return payload