1+ import dataclasses
12import json
23import logging
34import openai
1112_logger = logging .getLogger (__name__ )
1213
1314
15+ def threads_bot (
16+ api_key : str | None = None , base_url : str | None = None
17+ ) -> Bot :
18+ client = openai .OpenAI (api_key = api_key , base_url = base_url )
19+ return _ThreadsBot .create (client )
20+
21+
22+ # https://aider.chat/docs/more-info.html
23+ # https://github.com/Aider-AI/aider/blob/main/aider/prompts.py
24+ _INSTRUCTIONS = """\
25+ You are an expert software engineer, who writes correct and concise code.
26+ Use the provided functions to find the filesyou need to answer the query,
27+ read the content of the relevant ones, and save the changes you suggest.
28+ When writing a file, include a summary description of the changes you have
29+ made.
30+ """
31+
32+
1433def _function_tool_param (
1534 name : str ,
1635 description : str ,
@@ -75,18 +94,21 @@ def _function_tool_param(
7594]
7695
7796
78- # https://aider.chat/docs/more-info.html
79- # https://github.com/Aider-AI/aider/blob/main/aider/prompts.py
80- _INSTRUCTIONS = """\
81- You are an expert software engineer, who writes correct and concise code.
82- Use the provided functions to find the filesyou need to answer the query,
83- read the content of the relevant ones, and save the changes you suggest.
84- When writing a file, include a summary description of the changes you have
85- made.
86- """
97+ @dataclasses .dataclass (frozen = True )
98+ class _AssistantConfig :
99+ instructions : str
100+ model : str
101+ tools : Sequence [openai .types .beta .AssistantToolParam ]
102+
87103
104+ _assistant_config = _AssistantConfig (
105+ instructions = _INSTRUCTIONS ,
106+ model = "gpt-4o" ,
107+ tools = _tools ,
108+ )
88109
89- class OpenAIBot (Bot ):
110+
111+ class _ThreadsBot (Bot ):
90112 """An OpenAI-backed bot
91113
92114 See the following links for resources:
@@ -97,16 +119,27 @@ class OpenAIBot(Bot):
97119 * https://github.com/openai/openai-python/blob/main/src/openai/resources/beta/threads/runs/runs.py
98120 """
99121
100- def __init__ (self ) -> None :
101- self ._client = openai .OpenAI ()
122+ def __init__ (self , client : openai .OpenAI , assistant_id : str ) -> None :
123+ self ._client = client
124+ self ._assistant_id = assistant_id
125+
126+ @classmethod
127+ def create (cls , client : openai .OpenAI ) -> Self :
128+ path = cls .state_folder_path (ensure_exists = True ) / "ASSISTANT_ID"
129+ config = dataclasses .asdict (_assistant_config )
130+ try :
131+ with open (path ) as f :
132+ assistant_id = f .read ()
133+ except FileNotFoundError :
134+ assistant = client .beta .assistants .create (** config )
135+ assistant_id = assistant .id
136+ with open (path , "w" ) as f :
137+ f .write (assistant_id )
138+ else :
139+ client .beta .assistants .update (assistant_id , ** config )
140+ return cls (client , assistant_id )
102141
103142 def act (self , prompt : str , toolbox : Toolbox ) -> Action :
104- # TODO: Reuse assistant.
105- assistant = self ._client .beta .assistants .create (
106- instructions = _INSTRUCTIONS ,
107- model = "gpt-4o" ,
108- tools = _tools ,
109- )
110143 thread = self ._client .beta .threads .create ()
111144
112145 self ._client .beta .threads .messages .create (
@@ -117,7 +150,7 @@ def act(self, prompt: str, toolbox: Toolbox) -> Action:
117150
118151 with self ._client .beta .threads .runs .stream (
119152 thread_id = thread .id ,
120- assistant_id = assistant . id ,
153+ assistant_id = self . _assistant_id ,
121154 event_handler = _EventHandler (self ._client , toolbox ),
122155 ) as stream :
123156 stream .until_done ()
0 commit comments