Notas varias | Personalización del analizador de salida en LangChain (tomando como ejemplo el análisis de bloques de código Markdown)


01 Introducción al analizador de salida LangChain

Documentación oficial sobre el portal del analizador de salida:

https://python.langchain.com/docs/modules/model_io/output_parsers

El analizador de salida en LangChain pertenece 提示词模板a la categoría. En pocas palabras, agrega una descripción del formato de salida a la plantilla de palabras del mensaje y luego espera que el modelo grande genere contenido que se ajuste al formato, y luego analizamos los resultados. .

Un efecto similar al siguiente:

prompt = """
请给我3个有关天空的形容词。

你的输出需要以逗号分隔,例如:
good, nice, wonderful

你的输出:
"""

Con el analizador de salida, cuando creamos múltiples cadenas para el procesamiento de canalizaciones, podemos asegurarnos de que la entrada y la salida de cada cadena cumplan con las expectativas de formato, asegurando así la estabilidad de toda la cadena.

En la documentación oficial, se proporcionan 5 analizadores de salida principales, a saber:

  • Analizador de listas Analizador de listas, especificando la salida como formato de lista.
  • Analizador de fecha y hora, analizador de fecha y hora, que especifica que la salida satisface el formato de fecha y hora
  • Analizador de enumeración Analizador de enumeración, el valor de salida especificado solo puede ser un valor de enumeración
  • Analizador Pydantic (JSON) Analizador JSON, que especifica que el contenido de salida cumple con el formato JSON
  • El analizador de salida estructurado es un analizador de salida estructurado que recibe una clase personalizada y, según los campos y descripciones de la clase, el contenido devuelto satisface el paradigma JSON de la clase.

Sin embargo, la documentación oficial no menciona cómo personalizar un analizador de salida.

Este artículo toma el bloque de código de un documento Markdown como ejemplo para ilustrar cómo personalizar un analizador de salida.

02 Analizador de bloques de código Markdown personalizado

2.1 Descripción de requisitos

Quiero que la salida del modelo sea un bloque de código Markdown (o que contenga un bloque de código Markdown) para poder analizar el contenido del bloque de código.

Por ejemplo, en un escenario de uso clásico: convertir lenguaje natural a SQL, espero que las declaraciones SQL generadas por el modelo grande siempre estén empaquetadas en bloques de código Markdown para facilitar mi identificación y extracción.

2.2 Implementación de codificación

Cree un nuevo custom_parser.pyarchivo para lograr esto.

Aquí está el código:

import re
from typing import Any, Literal

from langchain.schema import BaseOutputParser, OutputParserException

# 自定义代码块输出解析器结构化指令的提示词
CUSTOM_CODE_BLOCK_INSTRUCTIONS = """
The output should be format as a Markdown-formatted Code Block.
Here is the output example:
```
(code content, such as sql,python,java,etc.)
```
"""


class CodeBlockOutputParser(BaseOutputParser[str]):
    """
    自定义一个代码块输出解析器,继承BaseOutputParser类,其中的泛型表示解析后要返回的数据类型。
    继承基类后,需要实现3个方法,分别是:
    parse -> 该方法用于解析大模型的输出,将其解析为既定格式,返回值即为泛型类型,例如在列表解析中返回类型为List
    get_format_instructions -> 该方法返回一段提示词,该提示词需要嵌入到原本的提示词模板中,作为对大模型返回格式的提示
    _type -> 这是一个只读的私有方法,调用该方法可获取解析器的类型,类型支持自命名
	"""
	# 自定义的一个字段,用于指定返回代码块的类型
    code_type: str = None

	# 在这段初始化方法中,指定了code_type只能为限定类型的代码
    def __init__(self, code_type: Literal["sql", "python", "java", "bash"] = "sql", **kwargs: Any):
        super().__init__(**kwargs)
        self.code_type = code_type

    def parse(self, text: str) -> str:
        """该方法用于解析模型的输出"""
        # 使用非贪婪匹配 .*? 来捕获三个反引号之间的任何内容
        pattern = r'```(.*?)```'

        # 执行搜索
        match = re.search(pattern, text, re.DOTALL)

        # 判断并输出结果
        if match:
            code = match.group(1)
            code = code.strip(self.code_type).strip()
            return code
        else:
            raise OutputParserException("The response has no code block.", llm_output=text)

    def get_format_instructions(self) -> str:
        """给出格式化指令"""
        return CUSTOM_CODE_BLOCK_INSTRUCTIONS

    @property
    def _type(self) -> str:
        """返回该解析器的类型 这里返回的是自定义代码块解析器"""
        return "CustomCodeBlock"

03 Utilice un analizador de salida personalizado

El uso del analizador de salida personalizado es el mismo que el uso del analizador de salida que viene con LangChain. El siguiente es el código de muestra:

from langchain import PromptTemplate, OpenAI
from custom_parser import CodeBlockOutputParser

# 创建大语言模型 API-KEY写在环境变量中了
llm = OpenAI(temperature=0)

# 写一个示例提示词模板,其中需要为格式化输出提示词预留空位
sql_prompt = "请为我写一个sql查询语句,查询user表中年龄在20到30岁之间用户的用户名。\n{format_instructions}"

# 创建代码块输出解析器对象
output_parser = CodeBlockOutputParser(code_type="sql")
format_instructions = output_parser.get_format_instructions()  # 获取格式化提示词

----------------------------------------------------------------------------------------------------

# 组装提示词
prompt = PromptTemplate(template=sql_prompt, input_variables=[], partial_variables={
    
    "format_instructions": format_instructions})
prompt = prompt.format()
print(f"提示词为:\n{
      
      prompt}")
"""
提示词为:
请为我写一个sql查询语句,查询user表中年龄在20到30岁之间用户的用户名。
The output should be format as a Markdown-formatted Code Block.
Here is the output example:
```
(code content, such as sql,python,java,etc.)
```
"""

----------------------------------------------------------------------------------------------------

# 调用大模型获取结果
output_raw = llm(prompt=prompt)
print(f"原始输出为:\n{
      
      output_raw}")
"""
原始输出为:
```
SELECT username FROM user WHERE age BETWEEN 20 AND 30;
```
"""

----------------------------------------------------------------------------------------------------
# 解析输出的结果
output = output_parser.parse(output_raw)
print(f"解析后的输出为:\n{
      
      output}")
"""
解析后的输出为:
SELECT username FROM user WHERE age BETWEEN 20 AND 30;
"""

(encima)

Supongo que te gusta

Origin blog.csdn.net/xuzhongyi103/article/details/132674772
Recomendado
Clasificación