auto-coder 0.1.226__py3-none-any.whl → 0.1.227__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 auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/METADATA +2 -2
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/RECORD +21 -19
- autocoder/auto_coder.py +424 -131
- autocoder/chat_auto_coder.py +267 -143
- autocoder/chat_auto_coder_lang.py +30 -1
- autocoder/common/__init__.py +2 -1
- autocoder/common/code_auto_generate.py +23 -9
- autocoder/common/code_auto_generate_diff.py +23 -9
- autocoder/common/code_auto_generate_editblock.py +23 -9
- autocoder/common/code_auto_generate_strict_diff.py +23 -9
- autocoder/common/command_completer.py +6 -0
- autocoder/common/types.py +1 -0
- autocoder/common/utils_code_auto_generate.py +38 -0
- autocoder/dispacher/actions/action.py +4 -4
- autocoder/dispacher/actions/plugins/action_regex_project.py +6 -2
- autocoder/models.py +158 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.226.dist-info → auto_coder-0.1.227.dist-info}/top_level.txt +0 -0
|
@@ -6,6 +6,7 @@ from autocoder.utils.queue_communicate import queue_communicate, CommunicateEven
|
|
|
6
6
|
from autocoder.common import sys_prompt
|
|
7
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
8
8
|
import json
|
|
9
|
+
from autocoder.common.utils_code_auto_generate import chat_with_continue
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class CodeAutoGenerateDiff:
|
|
@@ -336,35 +337,48 @@ class CodeAutoGenerateDiff:
|
|
|
336
337
|
|
|
337
338
|
conversations_list = []
|
|
338
339
|
results = []
|
|
340
|
+
input_tokens_count = 0
|
|
341
|
+
generated_tokens_count = 0
|
|
339
342
|
if not self.args.human_as_model:
|
|
340
343
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
341
344
|
futures = []
|
|
342
345
|
for llm in self.llms:
|
|
343
346
|
for _ in range(self.generate_times_same_model):
|
|
344
347
|
futures.append(executor.submit(
|
|
345
|
-
llm
|
|
346
|
-
|
|
348
|
+
chat_with_continue, llm=llm, conversations=conversations, llm_config=llm_config))
|
|
349
|
+
temp_results = [future.result() for future in futures]
|
|
350
|
+
for result in temp_results:
|
|
351
|
+
results.append(result.content)
|
|
352
|
+
input_tokens_count += result.input_tokens_count
|
|
353
|
+
generated_tokens_count += result.generated_tokens_count
|
|
354
|
+
|
|
347
355
|
for result in results:
|
|
348
356
|
conversations_list.append(
|
|
349
357
|
conversations + [{"role": "assistant", "content": result}])
|
|
350
358
|
else:
|
|
351
359
|
for _ in range(self.args.human_model_num):
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
360
|
+
single_result = chat_with_continue(llm=self.llms[0], conversations=conversations, llm_config=llm_config)
|
|
361
|
+
results.append(single_result.content)
|
|
362
|
+
input_tokens_count += single_result.input_tokens_count
|
|
363
|
+
generated_tokens_count += single_result.generated_tokens_count
|
|
355
364
|
conversations_list.append(
|
|
356
|
-
conversations + [{"role": "assistant", "content":
|
|
357
|
-
|
|
365
|
+
conversations + [{"role": "assistant", "content": single_result.content}])
|
|
366
|
+
|
|
367
|
+
statistics = {
|
|
368
|
+
"input_tokens_count": input_tokens_count,
|
|
369
|
+
"generated_tokens_count": generated_tokens_count
|
|
370
|
+
}
|
|
371
|
+
|
|
358
372
|
if self.args.request_id and not self.args.skip_events:
|
|
359
373
|
_ = queue_communicate.send_event(
|
|
360
374
|
request_id=self.args.request_id,
|
|
361
375
|
event=CommunicateEvent(
|
|
362
376
|
event_type=CommunicateEventType.CODE_GENERATE_END.value,
|
|
363
|
-
data=json.dumps(
|
|
377
|
+
data=json.dumps(statistics, ensure_ascii=False),
|
|
364
378
|
),
|
|
365
379
|
)
|
|
366
380
|
|
|
367
|
-
return CodeGenerateResult(contents=results, conversations=conversations_list)
|
|
381
|
+
return CodeGenerateResult(contents=results, conversations=conversations_list, metadata=statistics)
|
|
368
382
|
|
|
369
383
|
def multi_round_run(
|
|
370
384
|
self, query: str, source_content: str, max_steps: int = 10
|
|
@@ -10,6 +10,7 @@ from autocoder.utils.queue_communicate import (
|
|
|
10
10
|
)
|
|
11
11
|
import json
|
|
12
12
|
from concurrent.futures import ThreadPoolExecutor
|
|
13
|
+
from autocoder.common.utils_code_auto_generate import chat_with_continue
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class CodeAutoGenerateEditBlock:
|
|
@@ -418,34 +419,47 @@ class CodeAutoGenerateEditBlock:
|
|
|
418
419
|
|
|
419
420
|
conversations_list = []
|
|
420
421
|
results = []
|
|
422
|
+
input_tokens_count = 0
|
|
423
|
+
generated_tokens_count = 0
|
|
421
424
|
if not self.args.human_as_model:
|
|
422
425
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
423
426
|
futures = []
|
|
424
427
|
for llm in self.llms:
|
|
425
428
|
for _ in range(self.generate_times_same_model):
|
|
426
429
|
futures.append(executor.submit(
|
|
427
|
-
llm
|
|
428
|
-
|
|
430
|
+
chat_with_continue,llm=llm, conversations=conversations, llm_config=llm_config))
|
|
431
|
+
temp_results = [future.result() for future in futures]
|
|
432
|
+
for result in temp_results:
|
|
433
|
+
results.append(result.content)
|
|
434
|
+
input_tokens_count += result.input_tokens_count
|
|
435
|
+
generated_tokens_count += result.generated_tokens_count
|
|
436
|
+
|
|
429
437
|
for result in results:
|
|
430
438
|
conversations_list.append(
|
|
431
439
|
conversations + [{"role": "assistant", "content": result}])
|
|
432
440
|
else:
|
|
433
441
|
for _ in range(self.args.human_model_num):
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
442
|
+
single_result = chat_with_continue(llm=self.llms[0], conversations=conversations, llm_config=llm_config)
|
|
443
|
+
results.append(single_result.content)
|
|
444
|
+
input_tokens_count += single_result.input_tokens_count
|
|
445
|
+
generated_tokens_count += single_result.generated_tokens_count
|
|
446
|
+
conversations_list.append(conversations + [{"role": "assistant", "content": single_result.content}])
|
|
447
|
+
|
|
448
|
+
statistics = {
|
|
449
|
+
"input_tokens_count": input_tokens_count,
|
|
450
|
+
"generated_tokens_count": generated_tokens_count
|
|
451
|
+
}
|
|
452
|
+
|
|
439
453
|
if self.args.request_id and not self.args.skip_events:
|
|
440
454
|
_ = queue_communicate.send_event(
|
|
441
455
|
request_id=self.args.request_id,
|
|
442
456
|
event=CommunicateEvent(
|
|
443
457
|
event_type=CommunicateEventType.CODE_GENERATE_END.value,
|
|
444
|
-
data=json.dumps(
|
|
458
|
+
data=json.dumps(statistics, ensure_ascii=False),
|
|
445
459
|
),
|
|
446
460
|
)
|
|
447
461
|
|
|
448
|
-
return CodeGenerateResult(contents=results, conversations=conversations_list)
|
|
462
|
+
return CodeGenerateResult(contents=results, conversations=conversations_list, metadata=statistics)
|
|
449
463
|
|
|
450
464
|
def multi_round_run(
|
|
451
465
|
self, query: str, source_content: str, max_steps: int = 10
|
|
@@ -6,6 +6,7 @@ from autocoder.utils.queue_communicate import queue_communicate, CommunicateEven
|
|
|
6
6
|
from autocoder.common import sys_prompt
|
|
7
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
8
8
|
import json
|
|
9
|
+
from autocoder.common.utils_code_auto_generate import chat_with_continue
|
|
9
10
|
|
|
10
11
|
class CodeAutoGenerateStrictDiff:
|
|
11
12
|
def __init__(
|
|
@@ -306,34 +307,47 @@ class CodeAutoGenerateStrictDiff:
|
|
|
306
307
|
|
|
307
308
|
conversations_list = []
|
|
308
309
|
results = []
|
|
310
|
+
input_tokens_count = 0
|
|
311
|
+
generated_tokens_count = 0
|
|
309
312
|
if not self.args.human_as_model:
|
|
310
313
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
311
314
|
futures = []
|
|
312
315
|
for llm in self.llms:
|
|
313
316
|
for _ in range(self.generate_times_same_model):
|
|
314
317
|
futures.append(executor.submit(
|
|
315
|
-
llm
|
|
316
|
-
|
|
318
|
+
chat_with_continue, llm=llm, conversations=conversations, llm_config=llm_config))
|
|
319
|
+
temp_results = [future.result() for future in futures]
|
|
320
|
+
for result in temp_results:
|
|
321
|
+
results.append(result.content)
|
|
322
|
+
input_tokens_count += result.input_tokens_count
|
|
323
|
+
generated_tokens_count += result.generated_tokens_count
|
|
324
|
+
|
|
317
325
|
for result in results:
|
|
318
326
|
conversations_list.append(
|
|
319
327
|
conversations + [{"role": "assistant", "content": result}])
|
|
320
328
|
else:
|
|
321
329
|
for _ in range(self.args.human_model_num):
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
330
|
+
single_result = chat_with_continue(llm=self.llms[0], conversations=conversations, llm_config=llm_config)
|
|
331
|
+
results.append(single_result.content)
|
|
332
|
+
input_tokens_count += single_result.input_tokens_count
|
|
333
|
+
generated_tokens_count += single_result.generated_tokens_count
|
|
334
|
+
conversations_list.append(conversations + [{"role": "assistant", "content": single_result.content}])
|
|
335
|
+
|
|
336
|
+
statistics = {
|
|
337
|
+
"input_tokens_count": input_tokens_count,
|
|
338
|
+
"generated_tokens_count": generated_tokens_count
|
|
339
|
+
}
|
|
340
|
+
|
|
327
341
|
if self.args.request_id and not self.args.skip_events:
|
|
328
342
|
_ = queue_communicate.send_event(
|
|
329
343
|
request_id=self.args.request_id,
|
|
330
344
|
event=CommunicateEvent(
|
|
331
345
|
event_type=CommunicateEventType.CODE_GENERATE_END.value,
|
|
332
|
-
data=json.dumps(
|
|
346
|
+
data=json.dumps(statistics, ensure_ascii=False),
|
|
333
347
|
),
|
|
334
348
|
)
|
|
335
349
|
|
|
336
|
-
return CodeGenerateResult(contents=results, conversations=conversations_list)
|
|
350
|
+
return CodeGenerateResult(contents=results, conversations=conversations_list, metadata=statistics)
|
|
337
351
|
|
|
338
352
|
def multi_round_run(
|
|
339
353
|
self, query: str, source_content: str, max_steps: int = 10
|
autocoder/common/types.py
CHANGED
|
@@ -12,6 +12,7 @@ class StepNum(pydantic.BaseModel):
|
|
|
12
12
|
class CodeGenerateResult(pydantic.BaseModel):
|
|
13
13
|
contents:List[str]
|
|
14
14
|
conversations:List[List[Dict[str, Any]]]
|
|
15
|
+
metadata:Dict[str, Any] = {}
|
|
15
16
|
|
|
16
17
|
class MergeCodeWithoutEffect(pydantic.BaseModel):
|
|
17
18
|
success_blocks: List[Tuple[str, str]]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from byzerllm import ByzerLLM
|
|
2
|
+
from typing import List,Any,Union
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from loguru import logger
|
|
5
|
+
class ChatWithContinueResult(BaseModel):
|
|
6
|
+
content: str
|
|
7
|
+
input_tokens_count: int
|
|
8
|
+
generated_tokens_count: int
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def chat_with_continue(llm: ByzerLLM, conversations: List[dict], llm_config: dict) -> ChatWithContinueResult:
|
|
12
|
+
final_result = ChatWithContinueResult(content="", input_tokens_count=0, generated_tokens_count=0)
|
|
13
|
+
v = llm.chat_oai(
|
|
14
|
+
conversations=conversations, llm_config=llm_config)
|
|
15
|
+
|
|
16
|
+
single_result = v[0].output
|
|
17
|
+
metadata = v[0].metadata
|
|
18
|
+
|
|
19
|
+
final_result.input_tokens_count += metadata.get("input_tokens_count", 0)
|
|
20
|
+
final_result.generated_tokens_count += metadata.get("generated_tokens_count", 0)
|
|
21
|
+
|
|
22
|
+
temp_conversations = conversations + \
|
|
23
|
+
[{"role": "assistant", "content": single_result}]
|
|
24
|
+
|
|
25
|
+
count = 1
|
|
26
|
+
while (metadata.get("finish_reason", "stop") == "length" and count < 6):
|
|
27
|
+
v = llm.chat_oai(
|
|
28
|
+
conversations=temp_conversations, llm_config={**llm_config, "gen.response_prefix": True})
|
|
29
|
+
metadata = v[0].metadata
|
|
30
|
+
single_result += v[0].output
|
|
31
|
+
final_result.input_tokens_count += metadata.get("input_tokens_count", 0)
|
|
32
|
+
final_result.generated_tokens_count += metadata.get("generated_tokens_count", 0)
|
|
33
|
+
count += 1
|
|
34
|
+
|
|
35
|
+
# if count >= 2:
|
|
36
|
+
# logger.info(f"The code generation is exceed the max length, continue to generate the code {count -1 } times")
|
|
37
|
+
final_result.content = single_result
|
|
38
|
+
return final_result
|
|
@@ -116,7 +116,7 @@ class ActionTSProject(BaseAction):
|
|
|
116
116
|
generate_result = generate.single_round_run(
|
|
117
117
|
query=args.query, source_content=content
|
|
118
118
|
)
|
|
119
|
-
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds")
|
|
119
|
+
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds, input_tokens_count: {generate_result.metadata.get('input_tokens_count', 0)}, generated_tokens_count: {generate_result.metadata.get('generated_tokens_count', 0)}")
|
|
120
120
|
merge_result = None
|
|
121
121
|
if args.execute and args.auto_merge:
|
|
122
122
|
logger.info("Auto merge the code...")
|
|
@@ -200,7 +200,7 @@ class ActionPyScriptProject(BaseAction):
|
|
|
200
200
|
query=args.query, source_content=content
|
|
201
201
|
)
|
|
202
202
|
|
|
203
|
-
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds")
|
|
203
|
+
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds, input_tokens_count: {generate_result.metadata.get('input_tokens_count', 0)}, generated_tokens_count: {generate_result.metadata.get('generated_tokens_count', 0)}")
|
|
204
204
|
merge_result = None
|
|
205
205
|
if args.execute and args.auto_merge:
|
|
206
206
|
logger.info("Auto merge the code...")
|
|
@@ -302,7 +302,7 @@ class ActionPyProject(BaseAction):
|
|
|
302
302
|
generate_result = generate.single_round_run(
|
|
303
303
|
query=args.query, source_content=content
|
|
304
304
|
)
|
|
305
|
-
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds")
|
|
305
|
+
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds, input_tokens_count: {generate_result.metadata.get('input_tokens_count', 0)}, generated_tokens_count: {generate_result.metadata.get('generated_tokens_count', 0)}")
|
|
306
306
|
merge_result = None
|
|
307
307
|
if args.execute and args.auto_merge:
|
|
308
308
|
logger.info("Auto merge the code...")
|
|
@@ -396,7 +396,7 @@ class ActionSuffixProject(BaseAction):
|
|
|
396
396
|
query=args.query, source_content=content
|
|
397
397
|
)
|
|
398
398
|
|
|
399
|
-
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds")
|
|
399
|
+
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds, input_tokens_count: {generate_result.metadata.get('input_tokens_count', 0)}, generated_tokens_count: {generate_result.metadata.get('generated_tokens_count', 0)}")
|
|
400
400
|
merge_result = None
|
|
401
401
|
if args.execute and args.auto_merge:
|
|
402
402
|
logger.info("Auto merge the code...")
|
|
@@ -13,7 +13,7 @@ from autocoder.index.index import build_index_and_filter_files
|
|
|
13
13
|
from autocoder.regexproject import RegexProject
|
|
14
14
|
from autocoder.utils.conversation_store import store_code_model_conversation
|
|
15
15
|
from loguru import logger
|
|
16
|
-
|
|
16
|
+
import time
|
|
17
17
|
|
|
18
18
|
class ActionRegexProject:
|
|
19
19
|
def __init__(
|
|
@@ -51,8 +51,10 @@ class ActionRegexProject:
|
|
|
51
51
|
)
|
|
52
52
|
content = content[: self.args.model_max_input_length]
|
|
53
53
|
|
|
54
|
+
start_time = time.time()
|
|
54
55
|
if args.execute:
|
|
55
56
|
logger.info("Auto generate the code...")
|
|
57
|
+
|
|
56
58
|
if args.auto_merge == "diff":
|
|
57
59
|
generate = CodeAutoGenerateDiff(
|
|
58
60
|
llm=self.llm, args=self.args, action=self
|
|
@@ -75,6 +77,8 @@ class ActionRegexProject:
|
|
|
75
77
|
generate_result = generate.single_round_run(
|
|
76
78
|
query=args.query, source_content=content
|
|
77
79
|
)
|
|
80
|
+
|
|
81
|
+
logger.info(f"Code generation completed in {time.time() - start_time:.2f} seconds, input_tokens_count: {generate_result.metadata.get('input_tokens_count', 0)}, generated_tokens_count: {generate_result.metadata.get('generated_tokens_count', 0)}")
|
|
78
82
|
merge_result = None
|
|
79
83
|
if args.execute and args.auto_merge:
|
|
80
84
|
logger.info("Auto merge the code...")
|
|
@@ -90,7 +94,7 @@ class ActionRegexProject:
|
|
|
90
94
|
else:
|
|
91
95
|
code_merge = CodeAutoMerge(llm=self.llm, args=self.args)
|
|
92
96
|
merge_result = code_merge.merge_code(generate_result=generate_result)
|
|
93
|
-
|
|
97
|
+
|
|
94
98
|
if merge_result is not None:
|
|
95
99
|
content = merge_result.contents[0]
|
|
96
100
|
store_code_model_conversation(
|
autocoder/models.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from typing import List, Dict
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
|
|
6
|
+
MODELS_JSON = os.path.expanduser("~/.auto-coder/keys/models.json")
|
|
7
|
+
|
|
8
|
+
# Default built-in models
|
|
9
|
+
default_models_list = [
|
|
10
|
+
{
|
|
11
|
+
"name": "deepseek_r1_chat",
|
|
12
|
+
"description": "DeepSeek Reasoner is for design/review",
|
|
13
|
+
"model_name": "deepseek-reasoner",
|
|
14
|
+
"model_type": "saas/openai",
|
|
15
|
+
"base_url": "https://api.deepseek.com/v1",
|
|
16
|
+
"api_key_path": "api.deepseek.com"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "deepsee_chat",
|
|
20
|
+
"description": "DeepSeek Chat is for coding",
|
|
21
|
+
"model_name": "deepseek-chat",
|
|
22
|
+
"model_type": "saas/openai",
|
|
23
|
+
"base_url": "https://api.deepseek.com/v1",
|
|
24
|
+
"api_key_path": "api.deepseek.com"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name":"o1",
|
|
28
|
+
"description": "o1 is for design/review",
|
|
29
|
+
"model_name": "o1-2024-12-17",
|
|
30
|
+
"model_type": "saas/openai",
|
|
31
|
+
"base_url": "https://api.openai.com/v1",
|
|
32
|
+
"api_key_path": ""
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def load_models() -> List[Dict]:
|
|
37
|
+
"""
|
|
38
|
+
Load models from ~/.auto-coder/keys/models.json and merge with default_models_list.
|
|
39
|
+
Models are merged and deduplicated based on their name field.
|
|
40
|
+
If file doesn't exist or is invalid, use default_models_list.
|
|
41
|
+
"""
|
|
42
|
+
os.makedirs(os.path.dirname(MODELS_JSON), exist_ok=True)
|
|
43
|
+
|
|
44
|
+
# Start with default models
|
|
45
|
+
models_dict = {model["name"]: model for model in default_models_list}
|
|
46
|
+
|
|
47
|
+
# If JSON file exists, read and merge with defaults
|
|
48
|
+
if os.path.exists(MODELS_JSON):
|
|
49
|
+
try:
|
|
50
|
+
with open(MODELS_JSON, 'r', encoding='utf-8') as f:
|
|
51
|
+
custom_models = json.load(f)
|
|
52
|
+
# Custom models will override defaults with same name
|
|
53
|
+
for model in custom_models:
|
|
54
|
+
models_dict[model["name"]] = model
|
|
55
|
+
except json.JSONDecodeError:
|
|
56
|
+
# If JSON is invalid, just use defaults
|
|
57
|
+
save_models(default_models_list)
|
|
58
|
+
else:
|
|
59
|
+
# If file doesn't exist, create it with defaults
|
|
60
|
+
save_models(default_models_list)
|
|
61
|
+
|
|
62
|
+
# Convert merged dictionary back to list
|
|
63
|
+
target_models = list(models_dict.values())
|
|
64
|
+
api_key_dir = os.path.expanduser("~/.auto-coder/keys")
|
|
65
|
+
for model in target_models:
|
|
66
|
+
if model.get("api_key_path",""):
|
|
67
|
+
api_key_file = os.path.join(api_key_dir, model["api_key_path"])
|
|
68
|
+
if os.path.exists(api_key_file):
|
|
69
|
+
with open(api_key_file, "r") as f:
|
|
70
|
+
model["api_key"] = f.read()
|
|
71
|
+
return target_models
|
|
72
|
+
|
|
73
|
+
def save_models(models: List[Dict]) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Save models to ~/.auto-coder/keys/models.json
|
|
76
|
+
"""
|
|
77
|
+
os.makedirs(os.path.dirname(MODELS_JSON), exist_ok=True)
|
|
78
|
+
with open(MODELS_JSON, 'w', encoding='utf-8') as f:
|
|
79
|
+
json.dump(models, f, indent=2, ensure_ascii=False)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def process_api_key_path(base_url: str) -> str:
|
|
83
|
+
"""
|
|
84
|
+
从 base_url 中提取 host 部分并处理特殊字符
|
|
85
|
+
例如: https://api.example.com:8080/v1 -> api.example.com_8080
|
|
86
|
+
"""
|
|
87
|
+
if not base_url:
|
|
88
|
+
return ""
|
|
89
|
+
|
|
90
|
+
parsed = urlparse(base_url)
|
|
91
|
+
host = parsed.netloc
|
|
92
|
+
|
|
93
|
+
# 将冒号替换为下划线
|
|
94
|
+
host = host.replace(":", "_")
|
|
95
|
+
|
|
96
|
+
return host
|
|
97
|
+
|
|
98
|
+
def get_model_by_name(name: str) -> Dict:
|
|
99
|
+
"""
|
|
100
|
+
根据模型名称查找模型
|
|
101
|
+
"""
|
|
102
|
+
models = load_models()
|
|
103
|
+
v = [m for m in models if m["name"] == name.strip()]
|
|
104
|
+
|
|
105
|
+
if len(v) == 0:
|
|
106
|
+
raise Exception(f"Model {name} not found")
|
|
107
|
+
return v[0]
|
|
108
|
+
|
|
109
|
+
def update_model_with_api_key(name: str, api_key: str) -> Dict:
|
|
110
|
+
"""
|
|
111
|
+
根据模型名称查找并更新模型的 api_key_path。
|
|
112
|
+
如果找到模型,会根据其 base_url 处理 api_key_path。
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
name: 模型名称
|
|
116
|
+
api_key: API密钥
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Dict: 更新后的模型信息,如果未找到则返回None
|
|
120
|
+
"""
|
|
121
|
+
models = load_models()
|
|
122
|
+
|
|
123
|
+
# 在现有模型中查找
|
|
124
|
+
found_model = None
|
|
125
|
+
for model in models:
|
|
126
|
+
if model["name"] == name:
|
|
127
|
+
found_model = model
|
|
128
|
+
break
|
|
129
|
+
|
|
130
|
+
if not found_model:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
# 从 base_url 中提取并处理 host
|
|
134
|
+
api_key_path = process_api_key_path(found_model["base_url"])
|
|
135
|
+
if api_key_path:
|
|
136
|
+
found_model["api_key_path"] = api_key_path
|
|
137
|
+
|
|
138
|
+
# 保存 API 密钥
|
|
139
|
+
api_key_dir = os.path.expanduser("~/.auto-coder/keys")
|
|
140
|
+
os.makedirs(api_key_dir, exist_ok=True)
|
|
141
|
+
api_key_file = os.path.join(api_key_dir, api_key_path)
|
|
142
|
+
with open(api_key_file, "w") as f:
|
|
143
|
+
f.write(api_key)
|
|
144
|
+
|
|
145
|
+
# 如果是新模型,添加到模型列表中
|
|
146
|
+
if all(model["name"] != name for model in models):
|
|
147
|
+
models.append(found_model)
|
|
148
|
+
else:
|
|
149
|
+
# 更新现有模型
|
|
150
|
+
for i, model in enumerate(models):
|
|
151
|
+
if model["name"] == name:
|
|
152
|
+
models[i] = found_model
|
|
153
|
+
break
|
|
154
|
+
|
|
155
|
+
save_models(models)
|
|
156
|
+
|
|
157
|
+
return found_model
|
|
158
|
+
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.227"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|