femtowin commited on
Commit
cdba494
·
1 Parent(s): d80cfe4

feat: improve route configuration and UI layout - Add empty route option for automatic route selection, Move route dropdown to front, Move Answer section higher up, Update route handling to pass None for auto-selection

Browse files
Files changed (4) hide show
  1. CONFIG_GUIDE.md +113 -0
  2. README.md +1 -1
  3. app1.py +293 -20
  4. requirements.txt +2 -1
CONFIG_GUIDE.md ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Minion Brain Chat - LLM Configuration Guide
2
+
3
+ This application now supports flexible LLM configuration, allowing you to configure language models in multiple ways.
4
+
5
+ ## Features
6
+
7
+ ### 1. Preset Configurations
8
+ The application has built-in preset configurations loaded from `.env` file:
9
+ - **gpt-4o**: GPT-4o Azure configuration
10
+ - **gpt-4o-mini**: GPT-4o-mini Azure configuration
11
+ - **gpt-4.1**: GPT-4.1 Azure configuration
12
+ - **o4-mini**: O4-mini Azure configuration
13
+
14
+ ### 2. Custom Configuration
15
+ Select "Custom" option to fully customize all LLM parameters:
16
+ - API Type (openai, azure, ollama, groq, etc.)
17
+ - API Key
18
+ - Base URL
19
+ - API Version
20
+ - Model Name
21
+ - Temperature (0.0-2.0)
22
+ - Max Tokens (100-8000)
23
+
24
+ ### 3. Environment Variable Support
25
+ The application automatically loads configurations from `.env` file. Environment variable format:
26
+
27
+ ```bash
28
+ # GPT-4o Azure Configuration
29
+ GPT_4O_API_TYPE=azure
30
+ GPT_4O_API_KEY=your_api_key_here
31
+ GPT_4O_BASE_URL=https://your-endpoint.openai.azure.com/
32
+ GPT_4O_API_VERSION=2024-06-01
33
+ GPT_4O_TEMPERATURE=0
34
+ GPT_4O_MAX_TOKENS=4000
35
+ GPT_4O_MODEL=gpt-4o
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ### Method 1: Using Preset Configurations
41
+ 1. Select a preset configuration from "Preset Model" dropdown (e.g., gpt-4o)
42
+ 2. Other fields will automatically populate with corresponding configuration values
43
+ 3. Enter your question and submit
44
+
45
+ ### Method 2: Custom Configuration
46
+ 1. Select "Custom" from "Preset Model" dropdown
47
+ 2. Manually fill in all configuration fields:
48
+ - API Type: Choose provider type
49
+ - API Key: Enter your API key
50
+ - Base URL: Enter API base URL
51
+ - API Version: Enter API version (required for Azure)
52
+ - Model: Enter model name
53
+ - Temperature: Adjust generation randomness
54
+ - Max Tokens: Set maximum generation length
55
+ 3. Enter your question and submit
56
+
57
+ ## Security
58
+
59
+ - API keys are displayed as `***hidden***` in the interface
60
+ - `.env` file is added to `.gitignore` and won't be committed to version control
61
+
62
+ ## Configuration Examples
63
+
64
+ ### OpenAI Configuration
65
+ ```
66
+ API Type: openai
67
+ API Key: sk-your-openai-api-key
68
+ Base URL: https://api.openai.com/v1
69
+ API Version: (leave empty)
70
+ Model: gpt-4
71
+ Temperature: 0.7
72
+ Max Tokens: 4000
73
+ ```
74
+
75
+ ### Azure OpenAI Configuration
76
+ ```
77
+ API Type: azure
78
+ API Key: your-azure-api-key
79
+ Base URL: https://your-resource.openai.azure.com/
80
+ API Version: 2024-06-01
81
+ Model: gpt-4
82
+ Temperature: 0.7
83
+ Max Tokens: 4000
84
+ ```
85
+
86
+ ### Ollama Local Configuration
87
+ ```
88
+ API Type: ollama
89
+ API Key: (leave empty)
90
+ Base URL: http://localhost:11434
91
+ API Version: (leave empty)
92
+ Model: llama2
93
+ Temperature: 0.7
94
+ Max Tokens: 4000
95
+ ```
96
+
97
+ ## Troubleshooting
98
+
99
+ 1. **API Key Error**: Check if API key is correct and valid
100
+ 2. **Connection Error**: Verify if Base URL is correct
101
+ 3. **Permission Error**: Ensure API key has access to the specified model
102
+ 4. **Version Error**: For Azure, ensure API Version is correct
103
+
104
+ ## Updating Configuration
105
+
106
+ To update preset configurations:
107
+ 1. Edit the `.env` file
108
+ 2. Restart the application to load new configurations
109
+
110
+ To add new preset configurations:
111
+ 1. Add new environment variables in `.env` file
112
+ 2. Add new configuration in `get_preset_configs()` function in `app1.py`
113
+ 3. Restart the application
README.md CHANGED
@@ -5,7 +5,7 @@ colorFrom: yellow
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 5.32.0
8
- app_file: app.py
9
  pinned: false
10
  license: mit
11
  short_description: minion running in space
 
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 5.32.0
8
+ app_file: app1.py
9
  pinned: false
10
  license: mit
11
  short_description: minion running in space
app1.py CHANGED
@@ -1,6 +1,8 @@
1
  import gradio as gr
2
  import asyncio
3
  import os
 
 
4
 
5
  from minion import config
6
  from minion.main import LocalPythonEnv
@@ -8,12 +10,113 @@ from minion.main.rpyc_python_env import RpycPythonEnv
8
  from minion.main.brain import Brain
9
  from minion.providers import create_llm_provider
10
 
11
- # 初始化 brain(只初始化一次,避免每次请求都重建)
12
- def build_brain():
13
- model = "gpt-4.1"
14
- llm_config = config.models.get(model)
15
- llm = create_llm_provider(llm_config)
16
- #python_env = RpycPythonEnv(port=3007)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  python_env = LocalPythonEnv(verbose=False)
18
  brain = Brain(
19
  python_env=python_env,
@@ -21,23 +124,193 @@ def build_brain():
21
  )
22
  return brain
23
 
24
- brain = build_brain()
 
 
 
25
 
26
- async def minion_respond_async(query):
27
- obs, score, *_ = await brain.step(query=query, route="python", check=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  return obs
29
 
30
- def minion_respond(query):
31
- # gradio sync接口,自动调度async
32
- return asyncio.run(minion_respond_async(query))
33
-
34
- demo = gr.Interface(
35
- fn=minion_respond,
36
- inputs="text",
37
- outputs="text",
38
- title="Minion Brain Chat",
39
- description="用 Minion1 Brain 作为后端的智能问答"
40
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  if __name__ == "__main__":
43
  demo.launch(mcp_server=True)
 
1
  import gradio as gr
2
  import asyncio
3
  import os
4
+ from typing import Dict, Any
5
+ from dotenv import load_dotenv
6
 
7
  from minion import config
8
  from minion.main import LocalPythonEnv
 
10
  from minion.main.brain import Brain
11
  from minion.providers import create_llm_provider
12
 
13
+ # Load .env file
14
+ load_dotenv()
15
+
16
+ class LLMConfig:
17
+ def __init__(self, api_type: str, api_key: str, base_url: str, api_version: str,
18
+ model: str, temperature: float = 0.7, max_tokens: int = 4000,
19
+ vision_enabled: bool = False):
20
+ self.api_type = api_type
21
+ self.api_key = api_key
22
+ self.base_url = base_url
23
+ self.api_version = api_version
24
+ self.model = model
25
+ self.temperature = temperature
26
+ self.max_tokens = max_tokens
27
+ self.vision_enabled = vision_enabled
28
+
29
+ def get_preset_configs():
30
+ """Get preset configurations"""
31
+ presets = {
32
+ "gpt-4o": LLMConfig(
33
+ api_type=os.getenv("GPT_4O_API_TYPE", "azure"),
34
+ api_key=os.getenv("GPT_4O_API_KEY", ""),
35
+ base_url=os.getenv("GPT_4O_BASE_URL", ""),
36
+ api_version=os.getenv("GPT_4O_API_VERSION", "2024-06-01"),
37
+ model=os.getenv("GPT_4O_MODEL", "gpt-4o"),
38
+ temperature=float(os.getenv("GPT_4O_TEMPERATURE", "0")),
39
+ max_tokens=int(os.getenv("GPT_4O_MAX_TOKENS", "4000"))
40
+ ),
41
+ "gpt-4o-mini": LLMConfig(
42
+ api_type=os.getenv("GPT_4O_MINI_API_TYPE", "azure"),
43
+ api_key=os.getenv("GPT_4O_MINI_API_KEY", ""),
44
+ base_url=os.getenv("GPT_4O_MINI_BASE_URL", ""),
45
+ api_version=os.getenv("GPT_4O_MINI_API_VERSION", "2024-06-01"),
46
+ model=os.getenv("GPT_4O_MINI_MODEL", "gpt-4o-mini"),
47
+ temperature=float(os.getenv("GPT_4O_MINI_TEMPERATURE", "0.1")),
48
+ max_tokens=int(os.getenv("GPT_4O_MINI_MAX_TOKENS", "4000"))
49
+ ),
50
+ "gpt-4.1": LLMConfig(
51
+ api_type=os.getenv("GPT_41_API_TYPE", "azure"),
52
+ api_key=os.getenv("GPT_41_API_KEY", ""),
53
+ base_url=os.getenv("GPT_41_BASE_URL", ""),
54
+ api_version=os.getenv("GPT_41_API_VERSION", "2025-03-01-preview"),
55
+ model=os.getenv("GPT_41_MODEL", "gpt-4.1"),
56
+ temperature=float(os.getenv("GPT_41_TEMPERATURE", "0.7")),
57
+ max_tokens=int(os.getenv("GPT_41_MAX_TOKENS", "4000"))
58
+ ),
59
+ "o4-mini": LLMConfig(
60
+ api_type=os.getenv("O4_MINI_API_TYPE", "azure"),
61
+ api_key=os.getenv("O4_MINI_API_KEY", ""),
62
+ base_url=os.getenv("O4_MINI_BASE_URL", ""),
63
+ api_version=os.getenv("O4_MINI_API_VERSION", "2025-03-01-preview"),
64
+ model=os.getenv("O4_MINI_MODEL", "o4-mini"),
65
+ temperature=float(os.getenv("O4_MINI_TEMPERATURE", "0.7")),
66
+ max_tokens=int(os.getenv("O4_MINI_MAX_TOKENS", "4000"))
67
+ )
68
+ }
69
+ return presets
70
+
71
+ def get_default_config():
72
+ """Get default configuration"""
73
+ return LLMConfig(
74
+ api_type=os.getenv("DEFAULT_API_TYPE", "azure"),
75
+ api_key=os.getenv("DEFAULT_API_KEY", ""),
76
+ base_url=os.getenv("DEFAULT_BASE_URL", ""),
77
+ api_version=os.getenv("DEFAULT_API_VERSION", "2024-06-01"),
78
+ model=os.getenv("DEFAULT_MODEL", "gpt-4o"),
79
+ temperature=float(os.getenv("DEFAULT_TEMPERATURE", "0.7")),
80
+ max_tokens=int(os.getenv("DEFAULT_MAX_TOKENS", "4000"))
81
+ )
82
+
83
+ def get_available_routes():
84
+ """Get available route options for current minion system"""
85
+ return [
86
+ "", # Auto route selection (empty for automatic)
87
+ "raw", # Raw LLM output without processing
88
+ "native", # Native minion processing
89
+ "cot", # Chain of Thought reasoning
90
+ "dcot", # Dynamic Chain of Thought
91
+ "plan", # Planning-based approach
92
+ "python" # Python code execution
93
+ ]
94
+
95
+ def create_custom_llm_config(api_type: str, api_key: str, base_url: str,
96
+ api_version: str, model: str, temperature: float,
97
+ max_tokens: int) -> Dict[str, Any]:
98
+ """Create custom LLM configuration"""
99
+ return {
100
+ 'api_type': api_type,
101
+ 'api_key': api_key,
102
+ 'base_url': base_url,
103
+ 'api_version': api_version,
104
+ 'model': model,
105
+ 'temperature': temperature,
106
+ 'max_tokens': max_tokens,
107
+ 'vision_enabled': False
108
+ }
109
+
110
+ def build_brain_with_config(llm_config_dict: Dict[str, Any]):
111
+ """Build brain with specified configuration"""
112
+ # Create a config object similar to LLMConfig
113
+ class Config:
114
+ def __init__(self, config_dict):
115
+ for key, value in config_dict.items():
116
+ setattr(self, key, value)
117
+
118
+ config_obj = Config(llm_config_dict)
119
+ llm = create_llm_provider(config_obj)
120
  python_env = LocalPythonEnv(verbose=False)
121
  brain = Brain(
122
  python_env=python_env,
 
124
  )
125
  return brain
126
 
127
+ # Get preset configurations and default configuration
128
+ preset_configs = get_preset_configs()
129
+ default_config = get_default_config()
130
+ available_routes = get_available_routes()
131
 
132
+ async def minion_respond_async(query: str, preset_model: str, api_type: str,
133
+ api_key: str, base_url: str, api_version: str,
134
+ model: str, temperature: float, max_tokens: int,
135
+ route: str, check_enabled: bool):
136
+ """Respond to query using specified configuration"""
137
+
138
+ # If a preset model is selected, use preset configuration
139
+ if preset_model != "Custom":
140
+ config_obj = preset_configs.get(preset_model, default_config)
141
+ llm_config_dict = {
142
+ 'api_type': config_obj.api_type,
143
+ 'api_key': config_obj.api_key,
144
+ 'base_url': config_obj.base_url,
145
+ 'api_version': config_obj.api_version,
146
+ 'model': config_obj.model,
147
+ 'temperature': config_obj.temperature,
148
+ 'max_tokens': config_obj.max_tokens,
149
+ 'vision_enabled': config_obj.vision_enabled
150
+ }
151
+ else:
152
+ # Use custom configuration
153
+ llm_config_dict = create_custom_llm_config(
154
+ api_type, api_key, base_url, api_version, model, temperature, max_tokens
155
+ )
156
+
157
+ brain = build_brain_with_config(llm_config_dict)
158
+ # Handle empty route selection for auto route
159
+ route_param = route if route else None
160
+ obs, score, *_ = await brain.step(query=query, route=route_param, check=check_enabled)
161
  return obs
162
 
163
+ def minion_respond(query: str, preset_model: str, api_type: str, api_key: str,
164
+ base_url: str, api_version: str, model: str, temperature: float,
165
+ max_tokens: int, route: str, check_enabled: bool):
166
+ """Gradio sync interface, automatically schedules async"""
167
+ return asyncio.run(minion_respond_async(
168
+ query, preset_model, api_type, api_key, base_url,
169
+ api_version, model, temperature, max_tokens, route, check_enabled
170
+ ))
171
+
172
+ def update_fields(preset_model: str):
173
+ """Update other fields when preset model is selected"""
174
+ if preset_model == "Custom":
175
+ # Return default values, let user configure themselves
176
+ return (
177
+ default_config.api_type,
178
+ "", # Don't display API key
179
+ default_config.base_url,
180
+ default_config.api_version,
181
+ default_config.model,
182
+ default_config.temperature,
183
+ default_config.max_tokens
184
+ )
185
+ else:
186
+ config_obj = preset_configs.get(preset_model, default_config)
187
+ return (
188
+ config_obj.api_type,
189
+ "***hidden***", # Hide API key display
190
+ config_obj.base_url,
191
+ config_obj.api_version,
192
+ config_obj.model,
193
+ config_obj.temperature,
194
+ config_obj.max_tokens
195
+ )
196
+
197
+ # Create Gradio interface
198
+ with gr.Blocks(title="Minion Brain Chat") as demo:
199
+ gr.Markdown("# Minion Brain Chat\nIntelligent Q&A powered by Minion1 Brain")
200
+
201
+ with gr.Row():
202
+ with gr.Column(scale=2):
203
+ query_input = gr.Textbox(
204
+ label="Enter your question",
205
+ placeholder="Please enter your question...",
206
+ lines=3
207
+ )
208
+ submit_btn = gr.Button("Submit", variant="primary")
209
+
210
+ with gr.Column(scale=1):
211
+ # Move route selection to the front
212
+ route_dropdown = gr.Dropdown(
213
+ label="Route",
214
+ choices=available_routes,
215
+ value="",
216
+ info="empty: auto select, raw: direct LLM, native: standard, cot: chain of thought, dcot: dynamic cot, plan: planning, python: code execution"
217
+ )
218
+
219
+ # Add check option
220
+ check_checkbox = gr.Checkbox(
221
+ label="Enable Check",
222
+ value=False,
223
+ info="Enable output verification and validation"
224
+ )
225
+
226
+ preset_dropdown = gr.Dropdown(
227
+ label="Preset Model",
228
+ choices=["Custom"] + list(preset_configs.keys()),
229
+ value="gpt-4o",
230
+ info="Select preset configuration or custom"
231
+ )
232
+
233
+ api_type_input = gr.Textbox(
234
+ label="API Type",
235
+ value=default_config.api_type,
236
+ info="openai, azure, ollama, groq etc."
237
+ )
238
+
239
+ api_key_input = gr.Textbox(
240
+ label="API Key",
241
+ value="***hidden***",
242
+ type="password",
243
+ info="Your API key"
244
+ )
245
+
246
+ base_url_input = gr.Textbox(
247
+ label="Base URL",
248
+ value=default_config.base_url,
249
+ info="API base URL"
250
+ )
251
+
252
+ api_version_input = gr.Textbox(
253
+ label="API Version",
254
+ value=default_config.api_version,
255
+ info="API version (required for Azure)"
256
+ )
257
+
258
+ model_input = gr.Textbox(
259
+ label="Model",
260
+ value=default_config.model,
261
+ info="Model name"
262
+ )
263
+
264
+ temperature_input = gr.Slider(
265
+ label="Temperature",
266
+ minimum=0.0,
267
+ maximum=2.0,
268
+ value=default_config.temperature,
269
+ step=0.1,
270
+ info="Control output randomness"
271
+ )
272
+
273
+ max_tokens_input = gr.Slider(
274
+ label="Max Tokens",
275
+ minimum=100,
276
+ maximum=8000,
277
+ value=default_config.max_tokens,
278
+ step=100,
279
+ info="Maximum number of tokens to generate"
280
+ )
281
+
282
+ # Move Answer section up
283
+ output = gr.Textbox(
284
+ label="Answer",
285
+ lines=10,
286
+ show_copy_button=True
287
+ )
288
+
289
+ # Update other fields when preset model changes
290
+ preset_dropdown.change(
291
+ fn=update_fields,
292
+ inputs=[preset_dropdown],
293
+ outputs=[api_type_input, api_key_input, base_url_input,
294
+ api_version_input, model_input, temperature_input, max_tokens_input]
295
+ )
296
+
297
+ # Submit button event
298
+ submit_btn.click(
299
+ fn=minion_respond,
300
+ inputs=[query_input, preset_dropdown, api_type_input, api_key_input,
301
+ base_url_input, api_version_input, model_input, temperature_input,
302
+ max_tokens_input, route_dropdown, check_checkbox],
303
+ outputs=[output]
304
+ )
305
+
306
+ # Enter key submit
307
+ query_input.submit(
308
+ fn=minion_respond,
309
+ inputs=[query_input, preset_dropdown, api_type_input, api_key_input,
310
+ base_url_input, api_version_input, model_input, temperature_input,
311
+ max_tokens_input, route_dropdown, check_checkbox],
312
+ outputs=[output]
313
+ )
314
 
315
  if __name__ == "__main__":
316
  demo.launch(mcp_server=True)
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  gradio[mcp]==5.32.0
2
  huggingface_hub>=0.28.1
3
- minionx>=0.1.1
 
 
1
  gradio[mcp]==5.32.0
2
  huggingface_hub>=0.28.1
3
+ minionx>=0.1.2
4
+ python-dotenv>=1.0.0