找回密码
 立即注册
首页 业界区 安全 【langchain】prompt

【langchain】prompt

佟棠华 8 小时前
prompt源码分析

1.png

PromptTemplate

提示词模板,由一个字符串模板组成,接受用户输入的参数用来生成语言模型的提示词。
from_template方法
  1. @classmethod
  2. def from_template(
  3.     cls,
  4.     template: str,
  5.     *,
  6.     template_format: PromptTemplateFormat = "f-string",
  7.     partial_variables: Optional[dict[str, Any]] = None,
  8.     **kwargs: Any,
  9. ) -> PromptTemplate:
  10.     """
  11.     20250708 -
  12.     template 模板内容,如果是是用f""那么变量就需要赋值,如果是不带f直接使用{}那么就不需要赋值
  13.     PromptTemplateFormat 模板的格式类型,默认是f-string
  14.     partial_variables 带变量参数的模板,部分参数
  15.    
  16.     Load a prompt template from a template.
  17.     Args:
  18.         template: The template to load.
  19.         template_format: The format of the template. Use `jinja2` for jinja2,
  20.                             `mustache` for mustache, and `f-string` for f-strings.
  21.                             Defaults to `f-string`.
  22.         partial_variables: A dictionary of variables that can be used to partially
  23.                             fill in the template. For example, if the template is
  24.                             `"{variable1} {variable2}"`, and `partial_variables` is
  25.                             `{"variable1": "foo"}`, then the final prompt will be
  26.                             `"foo {variable2}"`. Defaults to None.
  27.         kwargs: Any other arguments to pass to the prompt template.
  28.     Returns:
  29.         The prompt template loaded from the template.
  30.     """
  31.     # 20250708 - 从模板中提取变量,默认是{}类型的变量
  32.     input_variables = get_template_variables(template, template_format)
  33.     # 20250708 - 字典对象,可以部分不设置
  34.     _partial_variables = partial_variables or {}
  35.     # 20250708 - 去掉部分不需要设置的参数
  36.     if _partial_variables:
  37.         input_variables = [
  38.             var for var in input_variables if var not in _partial_variables
  39.         ]
  40.         
  41.     # 20250708 - 实例化对象
  42.     return cls(
  43.         input_variables=input_variables,
  44.         template=template,
  45.         template_format=template_format,  # type: ignore[arg-type]
  46.         partial_variables=_partial_variables,
  47.         **kwargs,
  48.     )
复制代码
  1. from langchain_core.prompts import PromptTemplate
  2. t1 = "这是一个变量t1"
  3. PromptTemplate.from_template(f"测试template_format:{t1}")
  4. PromptTemplate.from_template("测试template_format:{t2}")
复制代码
2.png
  1. template1 = PromptTemplate.from_template("可以提前设置的变量{t1},测试template_format:{t2}", partial_variables={"t1":t1})
  2. template1.format(t2 = 'xxxxx')
复制代码
3.png

ChatPromptTemplate

这个提示词模板主要用于格式化消息列表,适用于多轮对话
  1. template = ChatPromptTemplate([
  2.                 ("system", "You are a helpful AI bot. Your name is {name}."),
  3.                 ("human", "Hello, how are you doing?"),
  4.                 ("ai", "I'm doing well, thanks!"),
  5.                 ("human", "{user_input}"),
  6.             ])
  7. from langchain_core.prompts import ChatPromptTemplate
  8. prompt_template = ChatPromptTemplate([
  9.     ("system", "You are a helpful assistant."),
  10.     ("user", "给我讲一个关于 {topic} 的笑话"),
  11.     ("assistant", "有一天,小明问他爸爸:“爸爸,我是不是傻孩子啊?”\n爸爸说:“傻孩子,你怎么会是傻孩子呢?”")
  12. ])
  13. prompt_template.invoke({"topic": "小孩"})
复制代码
4.png
  1. prompt_template1 = ChatPromptTemplate([
  2.     ("assistant", "有一天,小明问他爸爸:“爸爸,我是不是傻孩子啊?”\n爸爸说:“傻孩子,你怎么会是傻孩子呢?”"),
  3.     ("ai", "有一天sssssssscccccxxx"),
  4.     ("placeholder", "{param_test1}"),
  5.     ("placeholder", ["{param_test1}", True]),
  6. ])
  7. prompt_template1
复制代码
5.png

MessagesPlaceholder & callback

在刚刚的chat提示词模板中可以格式化多个消息列表,每个消息都是字符串,但是如果我们希望直接传一个消息数组,并放入特定位置,那么就需要用到这个类
6.png

其中ChatPromptTemplate的runnableconfig的callbacks对象是从外部传入handler对象,这个handler对象会传递到内部的callbackmanager对象,然后在通过configure内部的构造方法设置inheritable_callbacks对象为外部传入的callbackhandler对象
最后触发调用on_chain_start -》 handle_event -》 event = getattr(handler, event_name)(*args, **kwargs) -》 触发回调
  1. from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
  2. from langchain_core.messages import HumanMessage, AIMessage
  3. from langchain.callbacks.base import BaseCallbackHandler
  4. from langchain_core.runnables import RunnableConfig
  5. prompt_template = ChatPromptTemplate([
  6.     ("system", "You are a helpful assistant"),
  7.     MessagesPlaceholder("msgs"),
  8.     ("placeholder", ["{param_test1}", True])
  9. ])
  10. # 自定义回调类
  11. class MyCustomHandler(BaseCallbackHandler):
  12.     def on_chain_start(self, serialized, input, **kwargs):
  13.         print(f"开始执行: {input}")
  14.     def on_chain_end(self, output, **kwargs):
  15.         print(f"执行完成: {output}")
  16. config = RunnableConfig(
  17.     callbacks=[MyCustomHandler()]
  18. )
  19. pv1 = prompt_template.invoke({"msgs": [HumanMessage(content="hi!"), AIMessage(content="你好")], "param_test1":[
  20.     ("user", "给我讲一个关于 {topci1} 的笑话"),
  21.     ("ai", "有一天sssssssscccccxxx")
  22. ], "topci1":"cess"}, config=config)
  23. print(prompt_template.pretty_repr())
  24. pv1
复制代码
7.png

也可以直接用placeholder代表MessagesPlaceholder
  1. prompt_template = ChatPromptTemplate([
  2.     ("system", "You are a helpful assistant"),
  3.     ("placeholder", "{msgs}") # <-- This is the changed part
  4. ])
  5. prompt_template.invoke({"msgs": [HumanMessage(content="hi!"), AIMessage(content="你好")]})
复制代码
实质的底层调用format_prompt函数,进行数据格式化
少样本提示词模板:
  1. # 调用invoke的时候
  2. return self._call_with_config(
  3.             self._format_prompt_with_error_handling,
  4.             input,
  5.             config,
  6.             run_type="prompt",
  7.             serialized=self._serialized,
  8.         )
  9. with set_config_context(child_config) as context:
  10.         output = cast(
  11.             "Output",
  12.             context.run(
  13.                 call_func_with_variable_args,  # type: ignore[arg-type]
  14.                 func,
  15.                 input,
  16.                 config,
  17.                 run_manager,
  18.                 **kwargs,
  19.             ),
  20.         )
复制代码
# 调用invoke的时候
return self._call_with_config(
            self._format_prompt_with_error_handling,
            input,
            config,
            run_type="prompt",
            serialized=self._serialized,
        )

with set_config_context(child_config) as context:
        output = cast(
            "Output",
            context.run(
                call_func_with_variable_args,  # type: ignore[arg-type]
                func,
                input,
                config,
                run_manager,
                **kwargs,
            ),
        )


在调用大模型的时候,光有角色设定,用户输入得到的效果一般会比较差,需要通过给大模型一些参考样例,才能得到比较好的效果
  1. from langchain_core.prompts import PromptTemplateexample_prompt = PromptTemplate.from_template("Question: {question}\n{answer}")examples = [    {        "question": "Who lived longer, Muhammad Ali or Alan Turing?",        "answer": """1Are follow up questions needed here: Yes.Follow up: How old was Muhammad Ali when he died?Intermediate answer: Muhammad Ali was 74 years old when he died.Follow up: How old was Alan Turing when he died?Intermediate answer: Alan Turing was 41 years old when he died.So the final answer is: Muhammad Ali""",    },    {        "question": "When was the founder of craigslist born?",        "answer": """Are follow up questions needed here: Yes.Follow up: Who was the founder of craigslist?Intermediate answer: Craigslist was founded by Craig Newmark.Follow up: When was Craig Newmark born?Intermediate answer: Craig Newmark was born on December 6, 1952.So the final answer is: December 6, 1952""",    },    {        "question": "Who was the maternal grandfather of George Washington?",        "answer": """Are follow up questions needed here: Yes.Follow up: Who was the mother of George Washington?Intermediate answer: The mother of George Washington was Mary Ball Washington.Follow up: Who was the father of Mary Ball Washington?Intermediate answer: The father of Mary Ball Washington was Joseph Ball.So the final answer is: Joseph Ball""",    },    {        "question": "Are both the directors of Jaws and Casino Royale from the same country?",        "answer": """Are follow up questions needed here: Yes.Follow up: Who is the director of Jaws?Intermediate Answer: The director of Jaws is Steven Spielberg.Follow up: Where is Steven Spielberg from?Intermediate Answer: The United States.Follow up: Who is the director of Casino Royale?Intermediate Answer: The director of Casino Royale is Martin Campbell.Follow up: Where is Martin Campbell from?Intermediate Answer: New Zealand.So the final answer is: No""",    },]from langchain_core.prompts import # 调用invoke的时候
  2. return self._call_with_config(
  3.             self._format_prompt_with_error_handling,
  4.             input,
  5.             config,
  6.             run_type="prompt",
  7.             serialized=self._serialized,
  8.         )
  9. with set_config_context(child_config) as context:
  10.         output = cast(
  11.             "Output",
  12.             context.run(
  13.                 call_func_with_variable_args,  # type: ignore[arg-type]
  14.                 func,
  15.                 input,
  16.                 config,
  17.                 run_manager,
  18.                 **kwargs,
  19.             ),
  20.         )prompt = # 调用invoke的时候
  21. return self._call_with_config(
  22.             self._format_prompt_with_error_handling,
  23.             input,
  24.             config,
  25.             run_type="prompt",
  26.             serialized=self._serialized,
  27.         )
  28. with set_config_context(child_config) as context:
  29.         output = cast(
  30.             "Output",
  31.             context.run(
  32.                 call_func_with_variable_args,  # type: ignore[arg-type]
  33.                 func,
  34.                 input,
  35.                 config,
  36.                 run_manager,
  37.                 **kwargs,
  38.             ),
  39.         )(    examples=examples,    example_prompt=example_prompt,    suffix="Question: {input}",    input_variables=["input"],)print(    prompt.invoke({"input": "Who was the father of Mary Ball Washington?"}).to_string())
复制代码
8.png


  • 提示词模板部分格式化:
  1. FewShotPromptTemplate
复制代码
  1. from langchain_core.prompts import PromptTemplate
  2. example_prompt = PromptTemplate.from_template("Question: {question}\n{answer}")
  3. examples = [
  4.     {
  5.         "question": "Who lived longer, Muhammad Ali or Alan Turing?",
  6.         "answer": """1
  7. Are follow up questions needed here: Yes.
  8. Follow up: How old was Muhammad Ali when he died?
  9. Intermediate answer: Muhammad Ali was 74 years old when he died.
  10. Follow up: How old was Alan Turing when he died?
  11. Intermediate answer: Alan Turing was 41 years old when he died.
  12. So the final answer is: Muhammad Ali
  13. """,
  14.     },
  15.     {
  16.         "question": "When was the founder of craigslist born?",
  17.         "answer": """
  18. Are follow up questions needed here: Yes.
  19. Follow up: Who was the founder of craigslist?
  20. Intermediate answer: Craigslist was founded by Craig Newmark.
  21. Follow up: When was Craig Newmark born?
  22. Intermediate answer: Craig Newmark was born on December 6, 1952.
  23. So the final answer is: December 6, 1952
  24. """,
  25.     },
  26.     {
  27.         "question": "Who was the maternal grandfather of George Washington?",
  28.         "answer": """
  29. Are follow up questions needed here: Yes.
  30. Follow up: Who was the mother of George Washington?
  31. Intermediate answer: The mother of George Washington was Mary Ball Washington.
  32. Follow up: Who was the father of Mary Ball Washington?
  33. Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
  34. So the final answer is: Joseph Ball
  35. """,
  36.     },
  37.     {
  38.         "question": "Are both the directors of Jaws and Casino Royale from the same country?",
  39.         "answer": """
  40. Are follow up questions needed here: Yes.
  41. Follow up: Who is the director of Jaws?
  42. Intermediate Answer: The director of Jaws is Steven Spielberg.
  43. Follow up: Where is Steven Spielberg from?
  44. Intermediate Answer: The United States.
  45. Follow up: Who is the director of Casino Royale?
  46. Intermediate Answer: The director of Casino Royale is Martin Campbell.
  47. Follow up: Where is Martin Campbell from?
  48. Intermediate Answer: New Zealand.
  49. So the final answer is: No
  50. """,
  51.     },
  52. ]
  53. from langchain_core.prompts import FewShotPromptTemplate
  54. prompt = FewShotPromptTemplate(
  55.     examples=examples,
  56.     example_prompt=example_prompt,
  57.     suffix="Question: {input}",
  58.     input_variables=["input"],
  59. )
  60. print(
  61.     prompt.invoke({"input": "Who was the father of Mary Ball Washington?"}).to_string()
  62. )
复制代码
9.png


  • 提示词组合
    多个提示词连接起来,提示词内容可以有字符串,也可以是变量占位符
  1. Partial with strings
  2. Partial with functions
复制代码
总结


  • prompt默认一般就是f-string类型的字符串,通过变量替换的方式支持修改prompt
  • message支持有4种类型的消息:human,ai,system,placeholder,分别代表用户输入,ai生成,系统提示,最后有个位置占位符用来匹配不确定的内容,内容是数组
参考:

python中的@classmethod的作用

https://blog.csdn.net/qq_23981335/article/details/103798741

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册