?️ Haga que los LLM hablen el idioma de cada aplicación. ?️
Hecho con ❤️?️ por el equipo de .txt.
Canal de Youtube | Blog .txt | Gorjeo
pip install outlines
¿Primera vez aquí? Ir a nuestra guía de configuración
outlinesdev/outlines
!Outlines tiene nuevos lanzamientos y funciones cada semana. Asegúrate de destacar y ? Mire este repositorio, siga a @dottxtai para mantenerse actualizado.
Fundamos una empresa para seguir superando los límites de la generación estructurada. Obtenga más información sobre .txt y pruebe nuestra API .json si necesita una solución alojada
El primer paso hacia la confiabilidad de los sistemas que incluyen grandes modelos de lenguaje es garantizar que exista una interfaz bien definida entre su salida y el código definido por el usuario. Outlines proporciona formas de controlar la generación de modelos de lenguaje para hacer que su salida sea más predecible.
Puedes reducir la finalización a una elección entre múltiples posibilidades:
import outlines
model = outlines . models . transformers ( "microsoft/Phi-3-mini-4k-instruct" )
prompt = """You are a sentiment-labelling assistant.
Is the following review positive or negative?
Review: This restaurant is just awesome!
"""
generator = outlines . generate . choice ( model , [ "Positive" , "Negative" ])
answer = generator ( prompt )
Puede indicarle al modelo que solo devuelva números enteros o flotantes:
import outlines
model = outlines . models . transformers ( "WizardLM/WizardMath-7B-V1.1" )
prompt = "<s>result of 9 + 9 = 18</s><s>result of 1 + 2 = "
answer = outlines . generate . format ( model , int )( prompt )
print ( answer )
# 3
prompt = "sqrt(2)="
generator = outlines . generate . format ( model , float )
answer = generator ( prompt , max_tokens = 10 )
print ( answer )
# 1.41421356
Outlines también viene con una rápida generación estructurada de expresiones regulares. De hecho, las funciones choice
y format
utilizan sobre todo la generación estructurada con expresiones regulares bajo el capó:
import outlines
model = outlines . models . transformers ( "microsoft/Phi-3-mini-4k-instruct" )
prompt = "What is the IP address of the Google DNS servers? "
generator = outlines . generate . text ( model )
unstructured = generator ( prompt , max_tokens = 30 )
generator = outlines . generate . regex (
model ,
r"((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)" ,
)
structured = generator ( prompt , max_tokens = 30 )
print ( unstructured )
# What is the IP address of the Google DNS servers?
#
# Passive DNS servers are at DNS servers that are private.
# In other words, both IP servers are private. The database
# does not contain Chelsea Manning
print ( structured )
# What is the IP address of the Google DNS servers?
# 2.2.6.1
A diferencia de otras bibliotecas, la generación estructurada con expresiones regulares en Outlines es casi tan rápida como la generación no estructurada.
Outlines permite guiar el proceso de generación para garantizar que la salida siga un esquema JSON o modelo Pydantic:
from enum import Enum
from pydantic import BaseModel , constr
import outlines
import torch
class Weapon ( str , Enum ):
sword = "sword"
axe = "axe"
mace = "mace"
spear = "spear"
bow = "bow"
crossbow = "crossbow"
class Armor ( str , Enum ):
leather = "leather"
chainmail = "chainmail"
plate = "plate"
class Character ( BaseModel ):
name : constr ( max_length = 10 )
age : int
armor : Armor
weapon : Weapon
strength : int
model = outlines . models . transformers ( "microsoft/Phi-3-mini-4k-instruct" )
# Construct structured sequence generator
generator = outlines . generate . json ( model , Character )
# Draw a sample
seed = 789001
character = generator ( "Give me a character description" , seed = seed )
print ( repr ( character ))
# Character(name='Anderson', age=28, armor=<Armor.chainmail: 'chainmail'>, weapon=<Weapon.sword: 'sword'>, strength=8)
character = generator ( "Give me an interesting character description" )
print ( repr ( character ))
# Character(name='Vivian Thr', age=44, armor=<Armor.plate: 'plate'>, weapon=<Weapon.crossbow: 'crossbow'>, strength=125)
El método funciona con tipos de unión, tipos opcionales, matrices, esquemas anidados, etc. Algunas restricciones de campo aún no son compatibles, pero todo lo demás debería funcionar.
A veces simplemente desea poder pasar un esquema JSON en lugar de un modelo Pydantic. Lo tenemos cubierto:
import outlines
schema = '''{
"title": "Character",
"type": "object",
"properties": {
"name": {
"title": "Name",
"maxLength": 10,
"type": "string"
},
"age": {
"title": "Age",
"type": "integer"
},
"armor": {"$ref": "#/definitions/Armor"},
"weapon": {"$ref": "#/definitions/Weapon"},
"strength": {
"title": "Strength",
"type": "integer"
}
},
"required": ["name", "age", "armor", "weapon", "strength"],
"definitions": {
"Armor": {
"title": "Armor",
"description": "An enumeration.",
"enum": ["leather", "chainmail", "plate"],
"type": "string"
},
"Weapon": {
"title": "Weapon",
"description": "An enumeration.",
"enum": ["sword", "axe", "mace", "spear", "bow", "crossbow"],
"type": "string"
}
}
}'''
model = outlines . models . transformers ( "microsoft/Phi-3-mini-4k-instruct" )
generator = outlines . generate . json ( model , schema )
character = generator ( "Give me a character description" )
Las gramáticas formales gobiernan el mundo y Outlines hace que también gobiernen los LLM. Puede pasar cualquier gramática libre de contexto en el formato EBNF y Outlines generará un resultado que sea válido para esta gramática:
import outlines
arithmetic_grammar = """
?start: expression
?expression: term (("+" | "-") term)*
?term: factor (("*" | "/") factor)*
?factor: NUMBER
| "-" factor
| "(" expression ")"
%import common.NUMBER
"""
model = outlines . models . transformers ( "WizardLM/WizardMath-7B-V1.1" )
generator = outlines . generate . cfg ( model , arithmetic_grammar )
sequence = generator ( "Alice had 4 apples and Bob ate 2. Write an expression for Alice's apples:" )
print ( sequence )
# (8-2)
Esta era una gramática muy simple y puedes usar outlines.generate.cfg
para generar Python, SQL y mucho más sintácticamente válido. Cualquier tipo de texto estructurado, de verdad. Todo lo que tiene que hacer es buscar "gramática X EBNF" en la web y echar un vistazo al módulo grammars
esquemas.
Los contornos pueden inferir la estructura de la salida a partir de la firma de una función. El resultado es un diccionario y se puede pasar directamente a la función utilizando la sintaxis habitual de expansión del diccionario **
:
import outlines
def add ( a : int , b : int ):
return a + b
model = outlines . models . transformers ( "WizardLM/WizardMath-7B-V1.1" )
generator = outlines . generate . json ( model , add )
result = generator ( "Return json with two integers named a and b respectively. a is odd and b even." )
print ( add ( ** result ))
# 3
Una gran ventaja de pasar funciones directamente para especificar la estructura es que la estructura del LLM cambiará con la definición de la función. ¡No es necesario cambiar el código en varios lugares!
También puedes incrustar varias funciones en una enumeración para generar parámetros:
from enum import Enum
from functools import partial
import outlines
def add ( a : int , b : int ) -> int :
return a + b
def mul ( c : float , d : float ) -> float :
return c * d
class Operation ( Enum ):
add = partial ( add )
mul = partial ( mul )
model = outlines . models . transformers ( "WizardLM/WizardMath-7B-V1.1" )
generator = outlines . generate . json ( model , add )
result = generator ( "Return json with two float named c and d respectively. c is negative and d greater than 1.0." )
print ( result )
# {'c': -3.14, 'd': 1.5}
Las indicaciones de creación pueden resultar confusas. Outlines facilita la escritura y administración de mensajes al encapsular plantillas dentro de "funciones de plantilla".
Estas funciones permiten separar claramente la lógica del mensaje de la lógica general del programa; se pueden importar desde otros módulos y bibliotecas.
Las funciones de plantilla no requieren abstracciones superfluas; utilizan el motor de plantillas Jinja2 para ayudar a crear indicaciones complejas de manera concisa:
import outlines
examples = [
( "The food was disgusting" , "Negative" ),
( "We had a fantastic night" , "Positive" ),
( "Recommended" , "Positive" ),
( "The waiter was rude" , "Negative" )
]
@ outlines . prompt
def labelling ( to_label , examples ):
"""You are a sentiment-labelling assistant.
{% for example in examples %}
{{ example[0] }} // {{ example[1] }}
{% endfor %}
{{ to_label }} //
"""
model = outlines . models . transformers ( "microsoft/Phi-3-mini-4k-instruct" )
prompt = labelling ( "Just awesome" , examples )
answer = outlines . generate . text ( model )( prompt , max_tokens = 100 )
@article{willard2023efficient,
title={Efficient Guided Generation for LLMs},
author={Willard, Brandon T and Louf, R{'e}mi},
journal={arXiv preprint arXiv:2307.09702},
year={2023}
}