Pitonisa: Sacerdotisa del oráculo de Apolo en Delfos.
Pythoness de Emery Berger, extensión de Kyle Gwilt y Stephen Freund
Pythoness genera automáticamente código Python a partir de descripciones y pruebas en lenguaje natural.
Nota Pythoness necesita estar conectado a un LLM para poder funcionar. A continuación se muestra un ejemplo de cómo conectar Pythoness con una cuenta OpenAI. Para otros LLM, consulte su documentación.
Cuenta OpenAI. Su cuenta deberá tener un saldo positivo para que esto funcione (verifique su saldo). Si nunca ha comprado créditos, deberá comprar al menos $1 en créditos (si su cuenta API se creó antes del 13 de agosto de 2023) o $0,50 (si tiene una cuenta API más nueva). Obtenga una clave aquí.
Una vez que tenga una clave API, configúrela como una variable de entorno llamada
OPENAI_API_KEY
.export OPENAI_API_KEY= < your-api-key >
La forma más sencilla de instalar Pythoness es mediante pip:
python3 -m pip install pythoness
Para usar Pythoness, simplemente importe el módulo pythoness
y luego use el decorador @pythoness.spec
para especificar la funcionalidad deseada:
import pythoness
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." )
def myfib ( n : int ) -> int :
""
Este código generará internamente una función de Python llamada myfib
que calcula el enésimo número de la serie de Fibonacci. Para ejecutar realmente la función, puedes llamarla como lo harías con cualquier otra función de Python:
for i in range ( 20 ):
print ( myfib ( i ))
Pythoness almacena en caché los resultados de la traducción del lenguaje natural a Python, por lo que las ejecuciones posteriores en el mismo directorio se ejecutarán mucho más rápido (Pythoness crea una base de datos llamada pythoness-cache.db
que guarda estas traducciones).
Para desactivar todos los mensajes de registro, utilice la variable de entorno PYNS_QUIET
:
env PYNS_QUIET=1 python3 myfib.py
Puedes guiar a Pythoness proporcionando algunas pruebas. Pythoness utilizará pruebas tanto para generar el código Python como para validarlo. Las pruebas son solo una lista de cadenas que contienen código Python o funciones que deberían evaluarse como True
.
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." ,
tests = [ "myfib(1) == 1" , "myfib(2) == 1" ])
def myfib ( n : int ) -> int :
""
También puedes guiar a Pythoness con pruebas basadas en propiedades . Para hacer esto, describa las propiedades que desea que exhiba su programa. Pythoness ejecutará un probador basado en propiedades (hipótesis), que realizará pruebas muchas veces para garantizar que la función generada cumpla con las propiedades especificadas. Este enfoque es mucho más poderoso que las pruebas unitarias descritas anteriormente.
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." , tests = [({ 'n' : 'integers(1,20)' }, "myfib(n+2) == myfib(n+1)+myfib(n)" )])
def myfib ( n : int ) -> int :
""
Los TestCases del marco unittest integrado son la opción final para las pruebas y se pueden usar proporcionando Pythoness TestCases o un módulo de TestCases:
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." , tests = [ testmodule . TestFib ])
def myfib ( n : int ) -> int :
""
Puede guiar aún más a Pythoness dándole funciones y clases relacionadas con el código que generará. Utiliza la cadena de documentación de funciones y clases proporcionadas para comprender su propósito. Pythoness puede hacer uso de funciones que se generarán por sí mismo de esta manera, donde la cadena de documentación se especifica en spec
.
related_objs
es una lista que puede incluir funciones, clases o cadenas especiales:
'cls'
que representa todo en la clase que contiene la función generada, además de sí misma'*'
que representa todo el contenido del archivo que contiene la función generada, además de sí mismo @ pythoness . spec ( "Encodes a string using a single-shift Caesar cipher" )
def encode ( s : str ) -> str :
""
@ pythoness . spec ( "Decodes a string given to encode()" , related_objs = [ encode ])
def decode ( s : str ) -> str :
""
Cuando se trabaja con clases, es mejor utilizar la función __slots__
de Python. Si bien Pythoness puede funcionar sin él, esto aumenta la consistencia de Pythoness.
Puede hacer que Pythoness reemplace la especificación directamente en su archivo con la función generada: simplemente agregue `replace=True':
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." ,
tests = [ "myfib(1) == 1" , "myfib(2) == 1" ],
replace = True )
def myfib ( n : int ) -> int :
""
Por ejemplo, Pythoness produjo este código:
def myfib(n: int) -> int:
"""
Compute the nth number in the Fibonacci series.
:param n: The position of the desired number in the Fibonacci series
:type n: int
:return: The nth number in the Fibonacci series
:rtype: int
"""
if n <= 0:
raise ValueError("n must be a positive integer")
elif n == 1 or n == 2:
return 1
else:
fib1, fib2 = 1, 1
for _ in range(3, n + 1):
fib1, fib2 = fib2, fib1 + fib2
return fib2
También puedes reemplazar cada función generada usando la variable de entorno 'PYNS_REPLACE':
env ' PYNS_REPLACE ' =1
Pythoness ofrece algunas otras formas de controlar su comportamiento. Todos estos son argumentos para spec
. Los valores proporcionados indican el valor predeterminado.
max_retries=3
: controla el número máximo de reintentos debido a fallas (por ejemplo, una función que falla una de las pruebas proporcionadas).
model='gpt-4o'
: controla qué modelo LLM consultar
timeout_seconds=0
: establece la cantidad de tiempo para que se agote el tiempo de espera de un único intento de Pythoness. De forma predeterminada, no hay tiempo de espera.
verbose=False
: establezca esto en True
para que Pythoness genere detalles a medida que genera y valida el código. Principalmente útil para desarrolladores y para controlar el progreso. Se puede configurar para cada función a la vez usando la variable de entorno 'PYNS_VERBOSE'.
regenerate=False
: establece esto en True
para generar código nuevo cada vez que se llama a una función, en lugar de almacenarlo y reutilizarlo.
output=False
: establezca esto en True
para que Pythoness genere el código generado la primera vez que se llama a la función.