peichao.dong
commited on
Commit
·
7a27b40
1
Parent(s):
a72034e
refactor code generate tools
Browse files- .gitignore +1 -0
- README.md +15 -0
- code_generate.py → agents/code_generate_agent.py +8 -42
- agents/tools/api_layer_code_tool.py +95 -0
- agents/tools/domain_layer_code_tool.py +85 -0
- agents/tools/persistent_layer_code_tool.py +172 -0
- app.py +5 -7
- promopts.py +0 -306
.gitignore
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
__pycache__/*
|
|
|
2 |
.DS_Store
|
|
|
1 |
__pycache__/*
|
2 |
+
**/__pycache__/*
|
3 |
.DS_Store
|
README.md
CHANGED
@@ -11,3 +11,18 @@ license: apache-2.0
|
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
14 |
+
|
15 |
+
## 环境依赖
|
16 |
+
python3
|
17 |
+
|
18 |
+
## 安装依赖
|
19 |
+
|
20 |
+
```shell
|
21 |
+
pip install -r requirments
|
22 |
+
```
|
23 |
+
|
24 |
+
## 运行命令
|
25 |
+
|
26 |
+
```shell
|
27 |
+
python -m app.py
|
28 |
+
```
|
code_generate.py → agents/code_generate_agent.py
RENAMED
@@ -2,42 +2,14 @@ import re
|
|
2 |
from typing import List, Union
|
3 |
from langchain.chains import LLMChain
|
4 |
from langchain.chat_models import ChatOpenAI
|
5 |
-
from langchain.agents import
|
6 |
from langchain.schema import AgentAction, AgentFinish
|
7 |
from langchain.agents import initialize_agent
|
8 |
-
from langchain.memory import ConversationBufferMemory
|
9 |
from langchain.prompts import StringPromptTemplate
|
10 |
from promopts import code_generate_agent_template
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
from promopts import API_LAYER_PROMPT, DOMAIN_LAYER_PROMPT, PERSISTENT_LAYER_PROMPT
|
16 |
-
|
17 |
-
domainLayerChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=DOMAIN_LAYER_PROMPT)
|
18 |
-
|
19 |
-
persistentChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=PERSISTENT_LAYER_PROMPT)
|
20 |
-
|
21 |
-
apiChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=API_LAYER_PROMPT)
|
22 |
-
|
23 |
-
@tool("Generate Domain Layer Code", return_direct=True)
|
24 |
-
def domainLayerCodeGenerator(input: str) -> str:
|
25 |
-
'''useful for when you need to generate domain layer code'''
|
26 |
-
response = domainLayerChain.run(input)
|
27 |
-
return response
|
28 |
-
|
29 |
-
@tool("Generate Persistent Layer Code", return_direct=True)
|
30 |
-
def persistentLayerCodeGenerator(input: str) -> str:
|
31 |
-
'''useful for when you need to generate persistent layer code'''
|
32 |
-
response = persistentChain.run(input)
|
33 |
-
return response
|
34 |
-
|
35 |
-
@tool("Generate API Layer Code", return_direct=True)
|
36 |
-
def apiLayerCodeGenerator(input: str) -> str:
|
37 |
-
'''useful for when you need to generate API layer code'''
|
38 |
-
response = apiChain.run(input)
|
39 |
-
return response
|
40 |
-
|
41 |
|
42 |
|
43 |
class CustomPromptTemplate(StringPromptTemplate):
|
@@ -94,19 +66,13 @@ class CustomOutputParser(AgentOutputParser):
|
|
94 |
|
95 |
# agent = initialize_agent(
|
96 |
# tools=tools, llm=llm_chain, template=AGENT_PROMPT, stop=["\nObservation:"], agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
|
97 |
-
|
98 |
-
|
99 |
|
100 |
def code_agent_executor() -> AgentExecutor:
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
output_parser = CustomOutputParser()
|
105 |
-
|
106 |
-
|
107 |
AGENT_PROMPT = CustomPromptTemplate(
|
108 |
template=code_generate_agent_template,
|
109 |
-
tools=
|
110 |
# This omits the `agent_scratchpad`, `tools`, and `tool_names` variables because those are generated dynamically
|
111 |
# This includes the `intermediate_steps` variable because that is needed
|
112 |
input_variables=["input", "intermediate_steps"]
|
@@ -114,7 +80,7 @@ def code_agent_executor() -> AgentExecutor:
|
|
114 |
|
115 |
code_llm_chain = LLMChain(llm=ChatOpenAI(temperature=0.7), prompt=AGENT_PROMPT)
|
116 |
|
117 |
-
tool_names = [tool.name for tool in
|
118 |
code_agent = LLMSingleActionAgent(
|
119 |
llm_chain=code_llm_chain,
|
120 |
output_parser=output_parser,
|
@@ -123,7 +89,7 @@ def code_agent_executor() -> AgentExecutor:
|
|
123 |
)
|
124 |
|
125 |
code_agent_executor = AgentExecutor.from_agent_and_tools(
|
126 |
-
agent=code_agent, tools=
|
127 |
return code_agent_executor
|
128 |
|
129 |
# if __name__ == "__main__":
|
|
|
2 |
from typing import List, Union
|
3 |
from langchain.chains import LLMChain
|
4 |
from langchain.chat_models import ChatOpenAI
|
5 |
+
from langchain.agents import Tool, LLMSingleActionAgent, AgentExecutor, AgentOutputParser
|
6 |
from langchain.schema import AgentAction, AgentFinish
|
7 |
from langchain.agents import initialize_agent
|
|
|
8 |
from langchain.prompts import StringPromptTemplate
|
9 |
from promopts import code_generate_agent_template
|
10 |
+
from agents.tools.api_layer_code_tool import apiLayerCodeGenerator
|
11 |
+
from agents.tools.domain_layer_code_tool import domainLayerCodeGenerator
|
12 |
+
from agents.tools.persistent_layer_code_tool import persistentLayerCodeGenerator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
|
15 |
class CustomPromptTemplate(StringPromptTemplate):
|
|
|
66 |
|
67 |
# agent = initialize_agent(
|
68 |
# tools=tools, llm=llm_chain, template=AGENT_PROMPT, stop=["\nObservation:"], agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
|
69 |
+
code_agent_tools = [domainLayerCodeGenerator, persistentLayerCodeGenerator, apiLayerCodeGenerator]
|
|
|
70 |
|
71 |
def code_agent_executor() -> AgentExecutor:
|
|
|
|
|
|
|
72 |
output_parser = CustomOutputParser()
|
|
|
|
|
73 |
AGENT_PROMPT = CustomPromptTemplate(
|
74 |
template=code_generate_agent_template,
|
75 |
+
tools=code_agent_tools,
|
76 |
# This omits the `agent_scratchpad`, `tools`, and `tool_names` variables because those are generated dynamically
|
77 |
# This includes the `intermediate_steps` variable because that is needed
|
78 |
input_variables=["input", "intermediate_steps"]
|
|
|
80 |
|
81 |
code_llm_chain = LLMChain(llm=ChatOpenAI(temperature=0.7), prompt=AGENT_PROMPT)
|
82 |
|
83 |
+
tool_names = [tool.name for tool in code_agent_tools]
|
84 |
code_agent = LLMSingleActionAgent(
|
85 |
llm_chain=code_llm_chain,
|
86 |
output_parser=output_parser,
|
|
|
89 |
)
|
90 |
|
91 |
code_agent_executor = AgentExecutor.from_agent_and_tools(
|
92 |
+
agent=code_agent, tools=code_agent_tools, verbose=True)
|
93 |
return code_agent_executor
|
94 |
|
95 |
# if __name__ == "__main__":
|
agents/tools/api_layer_code_tool.py
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain import LLMChain, PromptTemplate
|
2 |
+
from langchain.chat_models import ChatOpenAI
|
3 |
+
from langchain.agents import tool
|
4 |
+
|
5 |
+
|
6 |
+
API_LAYER = """You are a software developer. Your task is to generate the api layer tests and product code.
|
7 |
+
|
8 |
+
===TechStack
|
9 |
+
Java17、reactor、lombok、Junit5、reactor test、Mockito、 Spring WebFlux、Spring Boot Test
|
10 |
+
===END OF TechStack
|
11 |
+
|
12 |
+
===Architecture
|
13 |
+
the api layer inclue 2 componets:
|
14 |
+
* DTO: This component is use to define data structure that api request and response.
|
15 |
+
* Controller: This component is use to define the interface to access api.
|
16 |
+
---eaxmple code:
|
17 |
+
@RestController
|
18 |
+
@RequiredArgsConstructor
|
19 |
+
@RequestMapping("/features")
|
20 |
+
public class FeatureController {{
|
21 |
+
private final Features features;
|
22 |
+
|
23 |
+
@GetMapping()
|
24 |
+
public Flux<Feature> findAll() {{
|
25 |
+
return features.getAll();
|
26 |
+
}}
|
27 |
+
|
28 |
+
@PostMapping()
|
29 |
+
public Mono<Feature> add(@RequestBody Feature feature) {{
|
30 |
+
return features.add(feature);
|
31 |
+
}}
|
32 |
+
}}
|
33 |
+
---end of eaxmple code
|
34 |
+
===END OF Architecture
|
35 |
+
|
36 |
+
===TestStrategy
|
37 |
+
For the Controller and DTO, we can write component test to test the actual implementation of api operations, test class rely on Association interface use WebFluxTest and WebTestClient ability.
|
38 |
+
---eaxmple code:
|
39 |
+
@ExtendWith(SpringExtension.class)
|
40 |
+
@WebFluxTest(value = FeatureFlagApi.class, properties = "spring.main.lazy-initialization=true")
|
41 |
+
@ContextConfiguration(classes = TestConfiguration.class)
|
42 |
+
class FeatureControllerTest extends ControllerTestBase {{
|
43 |
+
@Autowired
|
44 |
+
WebTestClient webClient;
|
45 |
+
|
46 |
+
@MockBean
|
47 |
+
Features features;
|
48 |
+
|
49 |
+
@Test
|
50 |
+
void should_getAll_success_when_no_records() {{
|
51 |
+
when(features.getAll(Mockito.any())).thenReturn(Flux.empty());
|
52 |
+
|
53 |
+
webClient.get()
|
54 |
+
.uri("/features")
|
55 |
+
.exchange()
|
56 |
+
.expectStatus()
|
57 |
+
.isOk()
|
58 |
+
.expectBodyList(FeatureFlagResponse.class)
|
59 |
+
.hasSize(0);
|
60 |
+
}}
|
61 |
+
}}
|
62 |
+
---end of eaxmple code
|
63 |
+
===END OF TestStrategy
|
64 |
+
|
65 |
+
Use the following format:
|
66 |
+
request: the request that you need to fulfill include Entity and Association of domain layer
|
67 |
+
|
68 |
+
DTO:
|
69 |
+
```
|
70 |
+
the DTO code that you write to fulfill the request, follow TechStack and Architecture
|
71 |
+
```
|
72 |
+
|
73 |
+
Controller:
|
74 |
+
```
|
75 |
+
the Controller code that you write to fulfill the request, follow TechStack and Architecture
|
76 |
+
```
|
77 |
+
|
78 |
+
Test:
|
79 |
+
```
|
80 |
+
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
81 |
+
```
|
82 |
+
|
83 |
+
request: {input}"""
|
84 |
+
|
85 |
+
API_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=API_LAYER,)
|
86 |
+
|
87 |
+
|
88 |
+
apiChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=API_LAYER_PROMPT)
|
89 |
+
|
90 |
+
|
91 |
+
@tool("Generate API Layer Code", return_direct=True)
|
92 |
+
def apiLayerCodeGenerator(input: str) -> str:
|
93 |
+
'''useful for when you need to generate API layer code'''
|
94 |
+
response = apiChain.run(input)
|
95 |
+
return response
|
agents/tools/domain_layer_code_tool.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain import LLMChain, PromptTemplate
|
2 |
+
from langchain.chat_models import ChatOpenAI
|
3 |
+
from langchain.agents import tool
|
4 |
+
|
5 |
+
|
6 |
+
DOMAIN_LAYER = """You are a software developer. Your task is to generate the domain layer tests and product code.
|
7 |
+
|
8 |
+
===TechStack
|
9 |
+
Java17、reactor、lombok、Junit5、reactor test、Mockito
|
10 |
+
===END OF TechStack
|
11 |
+
|
12 |
+
===Architecture
|
13 |
+
the domain layer inclue 2 componets:
|
14 |
+
* Entity: This component is use to represents business concepts and encapsulates business rules.
|
15 |
+
---eaxmple code:
|
16 |
+
public class Feature {{
|
17 |
+
private FeatureId id;
|
18 |
+
private FeatureDescription description;
|
19 |
+
|
20 |
+
public record FeatureId(String featureKey) {{
|
21 |
+
|
22 |
+
}}
|
23 |
+
|
24 |
+
@Builder
|
25 |
+
public record FeatureDescription(String name, String description, Boolean isEnable))) {{
|
26 |
+
|
27 |
+
}}
|
28 |
+
}}
|
29 |
+
---end of eaxmple code
|
30 |
+
* Association: This component is use to define association between entities, which can represents the concept of a set of entity.
|
31 |
+
---eaxmple code:
|
32 |
+
public interface Features {{
|
33 |
+
Flux<Feature> findAll();
|
34 |
+
|
35 |
+
Mono<Feature> findById(FeatureId id);
|
36 |
+
|
37 |
+
Mono<Feature> save(Feature feature);
|
38 |
+
|
39 |
+
Mono<Void> update(FeatureId id, FeatureDescription description);
|
40 |
+
|
41 |
+
Mono<Void> delete(FeatureId id);
|
42 |
+
|
43 |
+
Mono<Void> publish(FeatureId id);
|
44 |
+
|
45 |
+
Mono<Void> disable(FeatureId id);
|
46 |
+
}}
|
47 |
+
---end of eaxmple code
|
48 |
+
===END OF Architecture
|
49 |
+
|
50 |
+
===TestStrategy
|
51 |
+
For the Entity, we can write unit test to ensure that the business rules related to Merchandise are correctly encapsulated.
|
52 |
+
For the Association,do not write tests because it is has no impletation.
|
53 |
+
===END OF TestStrategy
|
54 |
+
|
55 |
+
Use the following format:
|
56 |
+
request: the request that you need to fulfill
|
57 |
+
|
58 |
+
Entity:
|
59 |
+
```
|
60 |
+
the Entity code that you write to fulfill the request, follow TechStack and Architecture
|
61 |
+
```
|
62 |
+
|
63 |
+
Association:
|
64 |
+
```
|
65 |
+
the Association code that you write to fulfill the request, follow TechStack and Architecture
|
66 |
+
```
|
67 |
+
|
68 |
+
Test:
|
69 |
+
```
|
70 |
+
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
71 |
+
```
|
72 |
+
|
73 |
+
request: {input}"""
|
74 |
+
|
75 |
+
|
76 |
+
DOMAIN_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=DOMAIN_LAYER,)
|
77 |
+
|
78 |
+
domainLayerChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=DOMAIN_LAYER_PROMPT)
|
79 |
+
|
80 |
+
|
81 |
+
@tool("Generate Domain Layer Code", return_direct=True)
|
82 |
+
def domainLayerCodeGenerator(input: str) -> str:
|
83 |
+
'''useful for when you need to generate domain layer code'''
|
84 |
+
response = domainLayerChain.run(input)
|
85 |
+
return response
|
agents/tools/persistent_layer_code_tool.py
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain import LLMChain, PromptTemplate
|
2 |
+
from langchain.chat_models import ChatOpenAI
|
3 |
+
from langchain.agents import tool
|
4 |
+
|
5 |
+
|
6 |
+
PERSISTENT_LAYER = """You are a software developer. Your task is to generate the persistent layer tests and product code.
|
7 |
+
|
8 |
+
===TechStack
|
9 |
+
Java17、reactor、lombok、Junit5、reactor test、Mockito、 Spring Data Reactive Couchbase、Testcontainers、Couchbase、WebClient
|
10 |
+
===END OF TechStack
|
11 |
+
|
12 |
+
===Architecture
|
13 |
+
the persistent layer inclue 3 componets:
|
14 |
+
* DbEntity: This component is use to define data structure that save to DB.
|
15 |
+
---eaxmple code:
|
16 |
+
@Document
|
17 |
+
public class FeatureDb {{
|
18 |
+
@Version
|
19 |
+
private long version;
|
20 |
+
|
21 |
+
@Id
|
22 |
+
@GeneratedValue(strategy = GenerationStrategy.UNIQUE)
|
23 |
+
private String id;
|
24 |
+
|
25 |
+
private String featureKey;
|
26 |
+
|
27 |
+
private Feature.FeatureDescription description;
|
28 |
+
}}
|
29 |
+
---end of eaxmple code
|
30 |
+
* Repository: This component is use to define the interface to access DB.
|
31 |
+
---eaxmple code:
|
32 |
+
public interface FeatureDbRepository extends ReactiveCrudRepository<FeatureDb, String> {{
|
33 |
+
Mono<FeatureDb> findByFeatureKey(String featureKey);
|
34 |
+
}}
|
35 |
+
---end of eaxmple code
|
36 |
+
* Association Impletation: This component provide implementation of Association of domain layer, rely on Repository.
|
37 |
+
---eaxmple code:
|
38 |
+
@Component
|
39 |
+
@RequiredArgsConstructor
|
40 |
+
public class FeaturesImpl implements Features{{
|
41 |
+
private final FeatureDbRepository featureDbRepository;
|
42 |
+
|
43 |
+
Flux<Feature> findAll() {{
|
44 |
+
return featureDbRepository.findAll().map(FeatureDb::toFeature);
|
45 |
+
}}
|
46 |
+
|
47 |
+
Mono<Feature> save(Feature feature) {{
|
48 |
+
return featureDbRepository.save(FeatureDb.fromFeature(feature)).map(FeatureDb::toFeature);
|
49 |
+
}}
|
50 |
+
}}
|
51 |
+
---end of eaxmple code
|
52 |
+
===END OF Architecture
|
53 |
+
|
54 |
+
===TestStrategy
|
55 |
+
For the DbEntity And Repository, we can write component test to test the actual implementation of database operations, test class should extends RepositoryTestBase to use Testcontainers ability.
|
56 |
+
---eaxmple code:
|
57 |
+
class FeatureDbRepositoryTest extends RepositoryTestBase {{
|
58 |
+
@Autowired
|
59 |
+
FeatureDbRepository repository;
|
60 |
+
|
61 |
+
@BeforeEach
|
62 |
+
void setUp() {{
|
63 |
+
repository.deleteAll().block();
|
64 |
+
}}
|
65 |
+
|
66 |
+
@AfterEach
|
67 |
+
void tearDown() {{
|
68 |
+
repository.deleteAll().block();
|
69 |
+
}}
|
70 |
+
|
71 |
+
@Test
|
72 |
+
void should_save_Feature_success() {{
|
73 |
+
var featureKey = "featureKey1";
|
74 |
+
repository.save(FeatureTestUtil.createFeatureDb(featureKey))
|
75 |
+
.as(StepVerifier::create)
|
76 |
+
.expectNextCount(1)
|
77 |
+
.verifyComplete();
|
78 |
+
}}
|
79 |
+
|
80 |
+
@Test
|
81 |
+
void should_add_same_featureKey_fail() {{
|
82 |
+
var featureKey = "featureKey1";
|
83 |
+
repository.save(FeatureTestUtil.createFeatureDb(featureKey)).block();
|
84 |
+
|
85 |
+
repository.save(FeatureTestUtil.createFeatureDb(featureKey))
|
86 |
+
.as(StepVerifier::create)
|
87 |
+
.expectError()
|
88 |
+
.verify();
|
89 |
+
}}
|
90 |
+
}}
|
91 |
+
---end of eaxmple code
|
92 |
+
For Association Impletation,we writ unit test, and stub repository method with Mockito.
|
93 |
+
---eaxmple code:
|
94 |
+
@ExtendWith(MockitoExtension.class)
|
95 |
+
class FeatureImplTest {{
|
96 |
+
@Mock
|
97 |
+
FeatureDbRepository repository;
|
98 |
+
|
99 |
+
Features features;
|
100 |
+
|
101 |
+
@BeforeEach
|
102 |
+
void setUp() {{
|
103 |
+
features = new FeaturesImpl(repository);
|
104 |
+
}}
|
105 |
+
|
106 |
+
@Test
|
107 |
+
void should_add_success() {{
|
108 |
+
when(repository.save(any(FeatureDb.class))).thenAnswer(invocation -> {{
|
109 |
+
FeatureDb featureDb = invocation.getArgument(0);
|
110 |
+
return Mono.just(featureDb);
|
111 |
+
}});
|
112 |
+
|
113 |
+
features.add(createFeature("featureKey1"))
|
114 |
+
.as(StepVerifier::create)
|
115 |
+
.expectNextMatches(config -> config.getId().featureKey().equals("featureKey1")
|
116 |
+
&& config.getDescription().updatedAt() != null
|
117 |
+
&& config.getDescription().createdAt() != null
|
118 |
+
)
|
119 |
+
.verifyComplete();
|
120 |
+
}}
|
121 |
+
|
122 |
+
@Test
|
123 |
+
void should_add_return_error_when_repository_save_error() {{
|
124 |
+
Feature feature = createFeature("featureKey1");
|
125 |
+
|
126 |
+
when(repository.save(any(FeatureDb.class))).thenReturn(Mono.error(new DuplicateKeyException("save error")));
|
127 |
+
|
128 |
+
features.add(feature)
|
129 |
+
.as(StepVerifier::create)
|
130 |
+
.expectError()
|
131 |
+
.verify();
|
132 |
+
}}
|
133 |
+
}}
|
134 |
+
|
135 |
+
|
136 |
+
===END OF TestStrategy
|
137 |
+
|
138 |
+
Use the following format:
|
139 |
+
request: the request that you need to fulfill include Entity and Association of domain layer
|
140 |
+
|
141 |
+
DBEntity:
|
142 |
+
```
|
143 |
+
the DBEntity code that you write to fulfill the request, follow TechStack and Architecture
|
144 |
+
```
|
145 |
+
|
146 |
+
Repository:
|
147 |
+
```
|
148 |
+
the Repository code that you write to fulfill the request, follow TechStack and Architecture
|
149 |
+
```
|
150 |
+
|
151 |
+
Association Impletation:
|
152 |
+
```
|
153 |
+
the Association Impletation code that you write to fulfill the request, follow TechStack and Architecture
|
154 |
+
```
|
155 |
+
|
156 |
+
Test:
|
157 |
+
```
|
158 |
+
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
159 |
+
```
|
160 |
+
|
161 |
+
request: {input}"""
|
162 |
+
|
163 |
+
PERSISTENT_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=PERSISTENT_LAYER,)
|
164 |
+
|
165 |
+
persistentChain = LLMChain(llm = ChatOpenAI(temperature=0.1), prompt=PERSISTENT_LAYER_PROMPT)
|
166 |
+
|
167 |
+
|
168 |
+
@tool("Generate Persistent Layer Code", return_direct=True)
|
169 |
+
def persistentLayerCodeGenerator(input: str) -> str:
|
170 |
+
'''useful for when you need to generate persistent layer code'''
|
171 |
+
response = persistentChain.run(input)
|
172 |
+
return response
|
app.py
CHANGED
@@ -7,7 +7,7 @@ from embedding import CustomEmbedding
|
|
7 |
from memories import HumenFeedbackBufferMemory
|
8 |
from langchain.memory import ConversationBufferMemory
|
9 |
from promopts import FEEDBACK, FEEDBACK_PROMPT
|
10 |
-
from
|
11 |
|
12 |
# llm = ChatOpenAI(temperature=0.7)
|
13 |
|
@@ -110,7 +110,8 @@ with gr.Blocks() as demo:
|
|
110 |
story = gr.Textbox(show_label=True, label="User Story", placeholder="Enter User Story").style(
|
111 |
container=False)
|
112 |
with gr.Row():
|
113 |
-
|
|
|
114 |
with gr.Row():
|
115 |
with gr.Column(scale=5):
|
116 |
gr.Button("Rewrite Context").click(rewriteContext, [context, chatbot], [chatbot, context])
|
@@ -136,7 +137,7 @@ with gr.Blocks() as demo:
|
|
136 |
with gr.Row():
|
137 |
relateCode = gr.Textbox(show_label=True, label="Relate Code", placeholder="Enter Relate Code").style(
|
138 |
container=False)
|
139 |
-
for index, tool in enumerate(
|
140 |
with gr.Row():
|
141 |
toolTextBox.append(gr.Textbox(show_label=False, visible=False, label=tool.name, value=tool.name).style())
|
142 |
gr.Button(tool.name).click(
|
@@ -148,10 +149,7 @@ with gr.Blocks() as demo:
|
|
148 |
faq = gr.Textbox(show_label=False, placeholder="Enter text and press enter").style(
|
149 |
container=False)
|
150 |
|
151 |
-
|
152 |
-
buisinessButton.click(clearMemory, [chatbot], [chatbot, txt]).then(sendMessage, [chatbot, txt], [chatbot]).then(
|
153 |
-
feedBack, [context, story, chatbot], [chatbot, txt])
|
154 |
-
|
155 |
txt.submit(sendMessage, [chatbot, txt], [chatbot]).then(
|
156 |
feedBack, [context, story, chatbot, txt], [chatbot, txt, context])
|
157 |
|
|
|
7 |
from memories import HumenFeedbackBufferMemory
|
8 |
from langchain.memory import ConversationBufferMemory
|
9 |
from promopts import FEEDBACK, FEEDBACK_PROMPT
|
10 |
+
from agents.code_generate_agent import code_agent_executor, code_agent_tools
|
11 |
|
12 |
# llm = ChatOpenAI(temperature=0.7)
|
13 |
|
|
|
110 |
story = gr.Textbox(show_label=True, label="User Story", placeholder="Enter User Story").style(
|
111 |
container=False)
|
112 |
with gr.Row():
|
113 |
+
gr.Button("Generate Scenarios").click(clearMemory, [chatbot], [chatbot, txt]).then(sendMessage, [chatbot, txt], [chatbot]).then(
|
114 |
+
feedBack, [context, story, chatbot], [chatbot, txt])
|
115 |
with gr.Row():
|
116 |
with gr.Column(scale=5):
|
117 |
gr.Button("Rewrite Context").click(rewriteContext, [context, chatbot], [chatbot, context])
|
|
|
137 |
with gr.Row():
|
138 |
relateCode = gr.Textbox(show_label=True, label="Relate Code", placeholder="Enter Relate Code").style(
|
139 |
container=False)
|
140 |
+
for index, tool in enumerate(code_agent_tools):
|
141 |
with gr.Row():
|
142 |
toolTextBox.append(gr.Textbox(show_label=False, visible=False, label=tool.name, value=tool.name).style())
|
143 |
gr.Button(tool.name).click(
|
|
|
149 |
faq = gr.Textbox(show_label=False, placeholder="Enter text and press enter").style(
|
150 |
container=False)
|
151 |
|
152 |
+
|
|
|
|
|
|
|
153 |
txt.submit(sendMessage, [chatbot, txt], [chatbot]).then(
|
154 |
feedBack, [context, story, chatbot, txt], [chatbot, txt, context])
|
155 |
|
promopts.py
CHANGED
@@ -50,320 +50,14 @@ Story: {input}
|
|
50 |
{agent_scratchpad}"""
|
51 |
|
52 |
|
53 |
-
DOMAIN_LAYER = """You are a software developer. Your task is to generate the domain layer tests and product code.
|
54 |
|
55 |
-
===TechStack
|
56 |
-
Java17、reactor、lombok、Junit5、reactor test、Mockito
|
57 |
-
===END OF TechStack
|
58 |
|
59 |
-
===Architecture
|
60 |
-
the domain layer inclue 2 componets:
|
61 |
-
* Entity: This component is use to represents business concepts and encapsulates business rules.
|
62 |
-
---eaxmple code:
|
63 |
-
public class Feature {{
|
64 |
-
private FeatureId id;
|
65 |
-
private FeatureDescription description;
|
66 |
|
67 |
-
public record FeatureId(String featureKey) {{
|
68 |
-
|
69 |
-
}}
|
70 |
|
71 |
-
@Builder
|
72 |
-
public record FeatureDescription(String name, String description, Boolean isEnable))) {{
|
73 |
-
|
74 |
-
}}
|
75 |
-
}}
|
76 |
-
---end of eaxmple code
|
77 |
-
* Association: This component is use to define association between entities, which can represents the concept of a set of entity.
|
78 |
-
---eaxmple code:
|
79 |
-
public interface Features {{
|
80 |
-
Flux<Feature> findAll();
|
81 |
|
82 |
-
Mono<Feature> findById(FeatureId id);
|
83 |
|
84 |
-
Mono<Feature> save(Feature feature);
|
85 |
|
86 |
-
Mono<Void> update(FeatureId id, FeatureDescription description);
|
87 |
|
88 |
-
Mono<Void> delete(FeatureId id);
|
89 |
-
|
90 |
-
Mono<Void> publish(FeatureId id);
|
91 |
-
|
92 |
-
Mono<Void> disable(FeatureId id);
|
93 |
-
}}
|
94 |
-
---end of eaxmple code
|
95 |
-
===END OF Architecture
|
96 |
-
|
97 |
-
===TestStrategy
|
98 |
-
For the Entity, we can write unit test to ensure that the business rules related to Merchandise are correctly encapsulated.
|
99 |
-
For the Association,do not write tests because it is has no impletation.
|
100 |
-
===END OF TestStrategy
|
101 |
-
|
102 |
-
Use the following format:
|
103 |
-
request: the request that you need to fulfill
|
104 |
-
|
105 |
-
Entity:
|
106 |
-
```
|
107 |
-
the Entity code that you write to fulfill the request, follow TechStack and Architecture
|
108 |
-
```
|
109 |
-
|
110 |
-
Association:
|
111 |
-
```
|
112 |
-
the Association code that you write to fulfill the request, follow TechStack and Architecture
|
113 |
-
```
|
114 |
-
|
115 |
-
Test:
|
116 |
-
```
|
117 |
-
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
118 |
-
```
|
119 |
-
|
120 |
-
request: {input}"""
|
121 |
-
|
122 |
-
|
123 |
-
DOMAIN_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=DOMAIN_LAYER,)
|
124 |
-
|
125 |
-
|
126 |
-
PERSISTENT_LAYER = """You are a software developer. Your task is to generate the persistent layer tests and product code.
|
127 |
-
|
128 |
-
===TechStack
|
129 |
-
Java17、reactor、lombok、Junit5、reactor test、Mockito、 Spring Data Reactive Couchbase、Testcontainers、Couchbase、WebClient
|
130 |
-
===END OF TechStack
|
131 |
-
|
132 |
-
===Architecture
|
133 |
-
the persistent layer inclue 3 componets:
|
134 |
-
* DbEntity: This component is use to define data structure that save to DB.
|
135 |
-
---eaxmple code:
|
136 |
-
@Document
|
137 |
-
public class FeatureDb {{
|
138 |
-
@Version
|
139 |
-
private long version;
|
140 |
-
|
141 |
-
@Id
|
142 |
-
@GeneratedValue(strategy = GenerationStrategy.UNIQUE)
|
143 |
-
private String id;
|
144 |
-
|
145 |
-
private String featureKey;
|
146 |
-
|
147 |
-
private Feature.FeatureDescription description;
|
148 |
-
}}
|
149 |
-
---end of eaxmple code
|
150 |
-
* Repository: This component is use to define the interface to access DB.
|
151 |
-
---eaxmple code:
|
152 |
-
public interface FeatureDbRepository extends ReactiveCrudRepository<FeatureDb, String> {{
|
153 |
-
Mono<FeatureDb> findByFeatureKey(String featureKey);
|
154 |
-
}}
|
155 |
-
---end of eaxmple code
|
156 |
-
* Association Impletation: This component provide implementation of Association of domain layer, rely on Repository.
|
157 |
-
---eaxmple code:
|
158 |
-
@Component
|
159 |
-
@RequiredArgsConstructor
|
160 |
-
public class FeaturesImpl implements Features{{
|
161 |
-
private final FeatureDbRepository featureDbRepository;
|
162 |
-
|
163 |
-
Flux<Feature> findAll() {{
|
164 |
-
return featureDbRepository.findAll().map(FeatureDb::toFeature);
|
165 |
-
}}
|
166 |
-
|
167 |
-
Mono<Feature> save(Feature feature) {{
|
168 |
-
return featureDbRepository.save(FeatureDb.fromFeature(feature)).map(FeatureDb::toFeature);
|
169 |
-
}}
|
170 |
-
}}
|
171 |
-
---end of eaxmple code
|
172 |
-
===END OF Architecture
|
173 |
-
|
174 |
-
===TestStrategy
|
175 |
-
For the DbEntity And Repository, we can write component test to test the actual implementation of database operations, test class should extends RepositoryTestBase to use Testcontainers ability.
|
176 |
-
---eaxmple code:
|
177 |
-
class FeatureDbRepositoryTest extends RepositoryTestBase {{
|
178 |
-
@Autowired
|
179 |
-
FeatureDbRepository repository;
|
180 |
-
|
181 |
-
@BeforeEach
|
182 |
-
void setUp() {{
|
183 |
-
repository.deleteAll().block();
|
184 |
-
}}
|
185 |
-
|
186 |
-
@AfterEach
|
187 |
-
void tearDown() {{
|
188 |
-
repository.deleteAll().block();
|
189 |
-
}}
|
190 |
-
|
191 |
-
@Test
|
192 |
-
void should_save_Feature_success() {{
|
193 |
-
var featureKey = "featureKey1";
|
194 |
-
repository.save(FeatureTestUtil.createFeatureDb(featureKey))
|
195 |
-
.as(StepVerifier::create)
|
196 |
-
.expectNextCount(1)
|
197 |
-
.verifyComplete();
|
198 |
-
}}
|
199 |
-
|
200 |
-
@Test
|
201 |
-
void should_add_same_featureKey_fail() {{
|
202 |
-
var featureKey = "featureKey1";
|
203 |
-
repository.save(FeatureTestUtil.createFeatureDb(featureKey)).block();
|
204 |
-
|
205 |
-
repository.save(FeatureTestUtil.createFeatureDb(featureKey))
|
206 |
-
.as(StepVerifier::create)
|
207 |
-
.expectError()
|
208 |
-
.verify();
|
209 |
-
}}
|
210 |
-
}}
|
211 |
-
---end of eaxmple code
|
212 |
-
For Association Impletation,we writ unit test, and stub repository method with Mockito.
|
213 |
-
---eaxmple code:
|
214 |
-
@ExtendWith(MockitoExtension.class)
|
215 |
-
class FeatureImplTest {{
|
216 |
-
@Mock
|
217 |
-
FeatureDbRepository repository;
|
218 |
-
|
219 |
-
Features features;
|
220 |
-
|
221 |
-
@BeforeEach
|
222 |
-
void setUp() {{
|
223 |
-
features = new FeaturesImpl(repository);
|
224 |
-
}}
|
225 |
-
|
226 |
-
@Test
|
227 |
-
void should_add_success() {{
|
228 |
-
when(repository.save(any(FeatureDb.class))).thenAnswer(invocation -> {{
|
229 |
-
FeatureDb featureDb = invocation.getArgument(0);
|
230 |
-
return Mono.just(featureDb);
|
231 |
-
}});
|
232 |
-
|
233 |
-
features.add(createFeature("featureKey1"))
|
234 |
-
.as(StepVerifier::create)
|
235 |
-
.expectNextMatches(config -> config.getId().featureKey().equals("featureKey1")
|
236 |
-
&& config.getDescription().updatedAt() != null
|
237 |
-
&& config.getDescription().createdAt() != null
|
238 |
-
)
|
239 |
-
.verifyComplete();
|
240 |
-
}}
|
241 |
-
|
242 |
-
@Test
|
243 |
-
void should_add_return_error_when_repository_save_error() {{
|
244 |
-
Feature feature = createFeature("featureKey1");
|
245 |
-
|
246 |
-
when(repository.save(any(FeatureDb.class))).thenReturn(Mono.error(new DuplicateKeyException("save error")));
|
247 |
-
|
248 |
-
features.add(feature)
|
249 |
-
.as(StepVerifier::create)
|
250 |
-
.expectError()
|
251 |
-
.verify();
|
252 |
-
}}
|
253 |
-
}}
|
254 |
-
|
255 |
-
|
256 |
-
===END OF TestStrategy
|
257 |
-
|
258 |
-
Use the following format:
|
259 |
-
request: the request that you need to fulfill include Entity and Association of domain layer
|
260 |
-
|
261 |
-
DBEntity:
|
262 |
-
```
|
263 |
-
the DBEntity code that you write to fulfill the request, follow TechStack and Architecture
|
264 |
-
```
|
265 |
-
|
266 |
-
Repository:
|
267 |
-
```
|
268 |
-
the Repository code that you write to fulfill the request, follow TechStack and Architecture
|
269 |
-
```
|
270 |
-
|
271 |
-
Association Impletation:
|
272 |
-
```
|
273 |
-
the Association Impletation code that you write to fulfill the request, follow TechStack and Architecture
|
274 |
-
```
|
275 |
-
|
276 |
-
Test:
|
277 |
-
```
|
278 |
-
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
279 |
-
```
|
280 |
-
|
281 |
-
request: {input}"""
|
282 |
-
|
283 |
-
PERSISTENT_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=PERSISTENT_LAYER,)
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
API_LAYER = """You are a software developer. Your task is to generate the api layer tests and product code.
|
288 |
-
|
289 |
-
===TechStack
|
290 |
-
Java17、reactor、lombok、Junit5、reactor test、Mockito、 Spring WebFlux、Spring Boot Test
|
291 |
-
===END OF TechStack
|
292 |
-
|
293 |
-
===Architecture
|
294 |
-
the api layer inclue 2 componets:
|
295 |
-
* DTO: This component is use to define data structure that api request and response.
|
296 |
-
* Controller: This component is use to define the interface to access api.
|
297 |
-
---eaxmple code:
|
298 |
-
@RestController
|
299 |
-
@RequiredArgsConstructor
|
300 |
-
@RequestMapping("/features")
|
301 |
-
public class FeatureController {{
|
302 |
-
private final Features features;
|
303 |
-
|
304 |
-
@GetMapping()
|
305 |
-
public Flux<Feature> findAll() {{
|
306 |
-
return features.getAll();
|
307 |
-
}}
|
308 |
-
|
309 |
-
@PostMapping()
|
310 |
-
public Mono<Feature> add(@RequestBody Feature feature) {{
|
311 |
-
return features.add(feature);
|
312 |
-
}}
|
313 |
-
}}
|
314 |
-
---end of eaxmple code
|
315 |
-
===END OF Architecture
|
316 |
-
|
317 |
-
===TestStrategy
|
318 |
-
For the Controller and DTO, we can write component test to test the actual implementation of api operations, test class rely on Association interface use WebFluxTest and WebTestClient ability.
|
319 |
-
---eaxmple code:
|
320 |
-
@ExtendWith(SpringExtension.class)
|
321 |
-
@WebFluxTest(value = FeatureFlagApi.class, properties = "spring.main.lazy-initialization=true")
|
322 |
-
@ContextConfiguration(classes = TestConfiguration.class)
|
323 |
-
class FeatureControllerTest extends ControllerTestBase {{
|
324 |
-
@Autowired
|
325 |
-
WebTestClient webClient;
|
326 |
-
|
327 |
-
@MockBean
|
328 |
-
Features features;
|
329 |
-
|
330 |
-
@Test
|
331 |
-
void should_getAll_success_when_no_records() {{
|
332 |
-
when(features.getAll(Mockito.any())).thenReturn(Flux.empty());
|
333 |
-
|
334 |
-
webClient.get()
|
335 |
-
.uri("/features")
|
336 |
-
.exchange()
|
337 |
-
.expectStatus()
|
338 |
-
.isOk()
|
339 |
-
.expectBodyList(FeatureFlagResponse.class)
|
340 |
-
.hasSize(0);
|
341 |
-
}}
|
342 |
-
}}
|
343 |
-
---end of eaxmple code
|
344 |
-
===END OF TestStrategy
|
345 |
-
|
346 |
-
Use the following format:
|
347 |
-
request: the request that you need to fulfill include Entity and Association of domain layer
|
348 |
-
|
349 |
-
DTO:
|
350 |
-
```
|
351 |
-
the DTO code that you write to fulfill the request, follow TechStack and Architecture
|
352 |
-
```
|
353 |
-
|
354 |
-
Controller:
|
355 |
-
```
|
356 |
-
the Controller code that you write to fulfill the request, follow TechStack and Architecture
|
357 |
-
```
|
358 |
-
|
359 |
-
Test:
|
360 |
-
```
|
361 |
-
the test code that you write to fulfill the request, follow TechStack Architecture and TestStrategy
|
362 |
-
```
|
363 |
-
|
364 |
-
request: {input}"""
|
365 |
-
|
366 |
-
API_LAYER_PROMPT = PromptTemplate(input_variables=["input"], template=API_LAYER,)
|
367 |
|
368 |
|
369 |
code_generate_agent_template = """You are a tool picker.
|
|
|
50 |
{agent_scratchpad}"""
|
51 |
|
52 |
|
|
|
53 |
|
|
|
|
|
|
|
54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
|
|
|
|
|
|
56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
|
62 |
|
63 |
code_generate_agent_template = """You are a tool picker.
|