Pitonisa: A sacerdotisa do oráculo de Apolo em Delfos.
Pythoness de Emery Berger, extensão de Kyle Gwilt e Stephen Freund
Pythoness gera automaticamente código Python a partir de descrições e testes de linguagem natural.
Nota Pythoness precisa estar conectado a um LLM para funcionar. Abaixo está um exemplo de como conectar Pythoness a uma conta OpenAI. Para outros LLMs, consulte sua documentação.
Conta OpenAI. Sua conta precisará ter saldo positivo para que isso funcione (verifique seu saldo). Se você nunca comprou créditos, precisará comprar pelo menos US$ 1 em créditos (se sua conta API foi criada antes de 13 de agosto de 2023) ou US$ 0,50 (se você tiver uma conta API mais recente). Obtenha uma chave aqui.
Depois de ter uma chave de API, defina-a como uma variável de ambiente chamada
OPENAI_API_KEY
.export OPENAI_API_KEY= < your-api-key >
A maneira mais fácil de instalar o Pythoness é através do pip:
python3 -m pip install pythoness
Para usar o Pythoness, basta importar o módulo pythoness
e usar o decorador @pythoness.spec
para especificar a funcionalidade desejada:
import pythoness
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." )
def myfib ( n : int ) -> int :
""
Este código irá gerar internamente uma função Python chamada myfib
que calcula o enésimo número da série Fibonacci. Para realmente executar a função, você pode chamá-la como faria com qualquer outra função Python:
for i in range ( 20 ):
print ( myfib ( i ))
O Pythoness armazena em cache os resultados da tradução da linguagem natural para Python, portanto, as execuções subsequentes no mesmo diretório serão executadas muito mais rapidamente (o Python cria um banco de dados chamado pythoness-cache.db
que salva essas traduções).
Para desativar todas as mensagens de registro, use a variável de ambiente PYNS_QUIET
:
env PYNS_QUIET=1 python3 myfib.py
Você pode orientar o Pythoness fornecendo alguns testes. Pythoness usará testes tanto para gerar o código Python quanto para validá-lo. Os testes são apenas uma lista de strings contendo código ou funções Python que devem ser avaliadas como True
.
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." ,
tests = [ "myfib(1) == 1" , "myfib(2) == 1" ])
def myfib ( n : int ) -> int :
""
Você também pode orientar o Pythoness com testes baseados em propriedades . Para fazer isso, descreva as propriedades que você deseja que seu programa exiba. Pythoness executará um testador baseado em propriedades (hipótese), que realizará testes várias vezes para garantir que a função gerada atenda às propriedades especificadas. Esta abordagem é muito mais poderosa que os testes unitários descritos acima.
@ 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 :
""
TestCases da estrutura unittest integrada são a opção final para teste e podem ser usados fornecendo Pythoness TestCases ou um módulo de TestCases:
@ pythoness . spec ( "Compute the nth number in the Fibonacci series." , tests = [ testmodule . TestFib ])
def myfib ( n : int ) -> int :
""
Você pode orientar ainda mais o Pythoness, fornecendo-lhe funções e classes relacionadas ao código que ele irá gerar. Ele usa a documentação das funções e classes fornecidas para entender sua finalidade. O Pythoness pode fazer uso de funções que serão geradas por ele mesmo desta forma, onde a docstring é especificada em spec
.
related_objs
é uma lista que pode incluir funções, classes ou strings especiais:
'cls'
que representa tudo na classe em que a função gerada está contida, além de si mesma'*'
que representa tudo no arquivo em que a função gerada está contida, além de si mesmo @ 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 :
""
Ao trabalhar com classes, é melhor usar o recurso __slots__
do Python. Embora o Pythoness possa funcionar sem ele, isso aumenta a consistência do Pythoness.
Você pode fazer com que o Pythoness substitua a especificação diretamente no seu arquivo pela função gerada: basta adicionar `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 exemplo, Pythoness produziu 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
Você também pode substituir todas as funções geradas usando a variável de ambiente 'PYNS_REPLACE':
env ' PYNS_REPLACE ' =1
Pythoness oferece algumas outras maneiras de controlar seu comportamento. Todos esses são argumentos para spec
. Os valores fornecidos indicam o valor padrão.
max_retries=3
: controla o número máximo de novas tentativas devido a falhas (por exemplo, uma função que falha em um dos testes fornecidos).
model='gpt-4o'
: controla qual modelo LLM consultar
timeout_seconds=0
: define a quantidade de tempo para uma única tentativa de Pythoness atingir o tempo limite. Por padrão, não há tempo limite.
verbose=False
: defina como True
para que o Pythoness produza detalhes à medida que gera e valida o código. Principalmente útil para desenvolvedores e para acompanhar o progresso. Pode ser definido para todas as funções de uma vez usando a variável de ambiente 'PYNS_VERBOSE'.
regenerate=False
: defina como True
para gerar um novo código toda vez que uma função for chamada, em vez de armazená-lo e reutilizá-lo.
output=False
: defina como True
para que o Pythoness produza o código gerado na primeira vez que a função for chamada.