Agent_Reflection_code_execution
April 25, 2024
[1]: !pip install -U --quiet langchain
!pip install --quiet langchain_openai
���������������������������������������� 817.7/817.7
kB 11.8 MB/s eta 0:00:00
���������������������������������������� 1.9/1.9 MB
25.3 MB/s eta 0:00:00
���������������������������������������� 291.3/291.3
kB 23.3 MB/s eta 0:00:00
���������������������������������������� 115.5/115.5
kB 12.1 MB/s eta 0:00:00
���������������������������������������� 49.4/49.4 kB
5.6 MB/s eta 0:00:00
���������������������������������������� 53.0/53.0 kB
5.6 MB/s eta 0:00:00
���������������������������������������� 141.1/141.1
kB 14.5 MB/s eta 0:00:00
���������������������������������������� 311.6/311.6
kB 9.1 MB/s eta 0:00:00
���������������������������������������� 1.8/1.8 MB
16.5 MB/s eta 0:00:00
���������������������������������������� 75.6/75.6 kB
6.9 MB/s eta 0:00:00
���������������������������������������� 77.9/77.9 kB
7.3 MB/s eta 0:00:00
���������������������������������������� 58.3/58.3 kB
5.5 MB/s eta 0:00:00
[2]: from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.pydantic_v1 import BaseModel, Field
1
[3]: from langchain_openai import ChatOpenAI
from google.colab import userdata
OPENAI_API_KEY = userdata.get('OPENAI_API_KEY')
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0,␣
↪api_key=OPENAI_API_KEY)
1 Data model of the outputed Python implemention code
[4]: # Data model
class code(BaseModel):
"""Code output"""
prefix: str = Field(description="Description of the trading strategy")
imports: str = Field(description="Code block import statements")
code: str = Field(description="Code block not including import statements")
name: str = Field(description="Name of the method")
parameters: str = Field(description="list of the parameters")
description = "Schema for code solutions to questions about algorithmic␣
↪trading strategies Python implementation."
2 Call the Generator Agent
[5]: prompt_generate = """You are a Python code generator specializing in␣
↪algorithmic trading. Your main role is to provide Python code solutions that␣
↪are straightforward, efficient, and strictly follow Pythonic principles.␣
↪Your responses should strictly consist of executable Python code tailored to␣
↪algorithmic trading strategies.
Please adhere to these protocols:
- Generate a code that is simple, efficient, optimized and the most␣
↪understandable possible.
- Augment your code by inline comments and docstrings, when it's necessary, to␣
↪clarify the functionality and the structure of the code.
- Make sure all code conforms to Python best practices and conventions.
- This code will be used as it is by the user, so make sure to generate an␣
↪executable code in prodution environment.
- Only produce executable Python code. Omit any explanatory text, descriptions,␣
↪or elements that are not code from your responses.
- Avoid using non-existent built-in methods, such as np.rolling or pd.rolling,␣
↪in well-known libraries.
- Be specific on the type of the prices you are implementing in the code.␣
↪Specify if it's a close, open, low, or high prices in each of your␣
↪implementation.
2
Answer only with Pyton code without any explanatory text, descriptions, or␣
↪elements that are not code from your responses.
"""
[ ]: prompt = ChatPromptTemplate.from_messages(
[
(
"system",
prompt_generate,
),
MessagesPlaceholder(variable_name="messages"),
]
)
generator = prompt | llm.with_structured_output(code)
#In this query I put "talib" library in purpose because it's not built-in␣
↪method which will generate an exec code error. It's an example to go␣
↪throught the whole process of reflection
query = "Propose a Python code for RSI, and be specific on the type of the␣
↪prices you are implementing in the code: close, open, high or low. Use talib␣
↪library"
request = HumanMessage(
content = query
)
resp = generator.invoke({"messages": [request]})
[100]: print(resp.code)
def calculate_rsi(close_prices, period=14):
rsi = talib.RSI(close_prices, timeperiod=period)
return rsi
3 Check if the code is executable
[65]: def exec_import(resp):
error_message=""
print("IMPORTS FOR THE STRATEGY\n")
print(resp.imports)
try:
exec(resp.imports)
print("---CODE IMPORT EXEC: SUCCEDDED---")
return None
except Exception as e:
print("---CODE IMPORT EXEC: FAILED---")
3
print(e)
message_e = f"The proposed code failed the import test: `{e}`"
error_message = HumanMessage(content= f"The import code is: '{resp.
↪imports}'. Message error: {message_e}")
return error_message
def exec_code(resp):
error_message=""
print("\nCODE STRATEGY\n")
print(resp.code)
try:
exec(resp.code)
print("---CODE IMPLEMNTATION EXEC: SUCCEDDED---")
return None
except Exception as e:
print("---CODE IMPLEMNTATION EXEC: FAILED---")
print(e)
message_e = f"The proposed code failed : `{e}`"
# error_message = HumanMessage(content=resp.code+ ". Message error:" +␣
↪message_e)
error_message = HumanMessage(content= f"The main code of the strategy is:
↪'{resp.code}'. Message error: {message_e}")
return error_message
[93]: messages = []
if exec_import(resp) !=None:
messages.append(exec_import(resp))
if exec_code(resp) !=None:
messages.append(exec_code(resp))
IMPORTS FOR THE STRATEGY
import talib
---CODE IMPORT EXEC: FAILED---
No module named 'talib'
IMPORTS FOR THE STRATEGY
import talib
---CODE IMPORT EXEC: FAILED---
No module named 'talib'
CODE STRATEGY
def calculate_rsi(close_prices, period=14):
rsi = talib.RSI(close_prices, timeperiod=period)
return rsi
4
---CODE IMPLEMNTATION EXEC: SUCCEDDED---
[68]: messages
[68]: [HumanMessage(content="The import code is: 'import talib'. Message error: The
proposed code failed the import test: `No module named 'talib'`")]
[59]: print(resp.prefix)
print(resp.imports)
print(resp.code)
print(resp.name)
print(resp.parameters)
Calculate Relative Strength Index (RSI) using close prices with talib library
import talib
def calculate_rsi(close_prices, period=14):
rsi = talib.RSI(close_prices, timeperiod=period)
return rsi
calculate_rsi
close_prices: List[float], period: int = 14
4 Reflection Agent
[94]: prompt_reflection = """
- The code execution has failed. It could be at the import libraries level or␣
↪at the code level.
- Reflect on this failure given the message error and propose a new Python code␣
↪implementation of the strategy requested by the user, for both the import␣
↪level and the code level.
- Avoid using the same code than the one failed. Propose another one.
- Generate a code that is simple, efficient, optimized and the most␣
↪understandable possible.
- Augment your code by inline comments and docstrings, when it's necessary, to␣
↪clarify the functionality and the structure of the code.
- Make sure all code conforms to Python best practices and conventions.
- Refrain from using non-existent built-in methods in well-known libraries.
"""
reflection_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
prompt_reflection,
),
MessagesPlaceholder(variable_name="messages"),
]
)
5
reflect = reflection_prompt | llm.with_structured_output(code)
query = "Propose a Python code for RSI, and be specific on the type of the␣
↪prices you are implementing in the code: close, open, high or low"
request = HumanMessage(
content = query
)
#If there is any error in the exec code: call the reflection agent
if messages != []:
print("MESSAGE TO ADD TO REFLECTION\n")
print(messages)
print("REFLECTION\n")
reflection = reflect.invoke({"messages": [request, messages[0]]})
print(reflection)
MESSAGE TO ADD TO REFLECTION
[HumanMessage(content="The import code is: 'import talib'. Message error: The
proposed code failed the import test: `No module named 'talib'`")]
REFLECTION
prefix='Calculating Relative Strength Index (RSI) using close prices'
imports='import numpy as np\nimport pandas as pd' code='def
calculate_rsi(close_prices, period=14):\n delta = close_prices.diff()\n
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()\n loss =
(-delta.where(delta < 0, 0)).rolling(window=period).mean()\n rs = gain /
loss\n rsi = 100 - (100 / (1 + rs))\n return rsi' name='calculate_rsi'
parameters='close_prices: pd.Series, period: int = 14' description='Function to
calculate the Relative Strength Index (RSI) using close prices'
4.0.1 The reflection agent replaces talib with buyilt-in methods and the test checking
if the code is executable is OK.
[95]: # messages = []
if exec_import(reflection) !=None:
messages.append(exec_import(reflection))
if exec_code(reflection) !=None:
messages.append(exec_code(reflection))
IMPORTS FOR THE STRATEGY
import numpy as np
import pandas as pd
---CODE IMPORT EXEC: SUCCEDDED---
6
CODE STRATEGY
def calculate_rsi(close_prices, period=14):
delta = close_prices.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
---CODE IMPLEMNTATION EXEC: SUCCEDDED---
5 If still a FAILED EXEC ==> add to the content “messages”
list the new erros and send it back to the reflection agent:
[85]: message_content =""
for mess in messages:
message_content += mess.content+"\n"
[96]: messages
[96]: [HumanMessage(content="The import code is: 'import talib'. Message error: The
proposed code failed the import test: `No module named 'talib'`")]
[ ]: mess_hum = HumanMessage(content=message_content)
5.1 Call the reflection agent with the new error messages
[88]: if messages != []:
print("MESSAGE TO ADD TO REFLECTION\n")
print(messages)
print("REFLECTION\n")
reflection = reflect.invoke({"messages": [request, mess_hum]})
print(reflection)
MESSAGE TO ADD TO REFLECTION
[HumanMessage(content="The import code is: 'import talib'. Message error: The
proposed code failed the import test: `No module named 'talib'`"),
HumanMessage(content="The import code is: 'import numpy as np\nimport pandas as
pd\nfrom talib.abstract import *'. Message error: The proposed code failed the
import test: `No module named 'talib'`"), HumanMessage(content="The import code
is: 'import numpy as np\nimport pandas as pd\nimport talib'. Message error: The
proposed code failed the import test: `No module named 'talib'`")]
REFLECTION
prefix='Calculate the Relative Strength Index (RSI) using closing prices'
7
imports='import numpy as np\nimport pandas as pd\nimport talib' code="# Define a
function to calculate RSI\n\ndef calculate_rsi(data, period=14):\n rsi =
talib.RSI(data['close'], timeperiod=period)\n return rsi"
name='calculate_rsi' parameters='data: pandas DataFrame, period: int = 14'
description='Function to calculate the Relative Strength Index (RSI) using
closing prices'
5.2 Then Check if any FAILED EXEC
[84]: # messages = []
if exec_import(reflection) !=None:
messages.append(exec_import(reflection))
if exec_code(reflection) !=None:
messages.append(exec_code(reflection))
IMPORTS FOR THE STRATEGY
import numpy as np
import pandas as pd
import talib
---CODE IMPORT EXEC: FAILED---
No module named 'talib'
IMPORTS FOR THE STRATEGY
import numpy as np
import pandas as pd
import talib
---CODE IMPORT EXEC: FAILED---
No module named 'talib'
CODE STRATEGY
def calculate_rsi(data, period=14):
data['RSI'] = talib.RSI(data['Close'], timeperiod=period)
return data
---CODE IMPLEMNTATION EXEC: SUCCEDDED---
[99]: # If both == None ==> no error from the execution of the proposed code ==>␣
↪messages = []
if exec_import(reflection) ==None and exec_code(reflection) ==None:
messages = []
IMPORTS FOR THE STRATEGY
import numpy as np
import pandas as pd
---CODE IMPORT EXEC: SUCCEDDED---
8
CODE STRATEGY
def calculate_rsi(close_prices, period=14):
delta = close_prices.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
---CODE IMPLEMNTATION EXEC: SUCCEDDED---
[98]: messages
[98]: []
And start again, adding it to the list of the messages and sending it back to the reflection agent.