diff --git a/developer_notes/prompt_note.py b/developer_notes/prompt_note.py
new file mode 100644
index 00000000..cb4bb167
--- /dev/null
+++ b/developer_notes/prompt_note.py
@@ -0,0 +1,84 @@
+def python_str_format_example(task_desc_str: str, input_str: str):
+
+ # percent(%) formatting
+ print("%s User: %s" % (task_desc_str, input_str))
+
+ # format() method with kwargs
+ print(
+ "{task_desc_str} User: {input_str}".format(
+ task_desc_str=task_desc_str, input_str=input_str
+ )
+ )
+
+ # f-string
+ print(f"{task_desc_str} User: {input_str}")
+
+ # Templates
+ from string import Template
+
+ t = Template("$task_desc_str User: $input_str")
+ print(t.substitute(task_desc_str=task_desc_str, input_str=input_str))
+
+
+def jinja2_template_example(template, **kwargs):
+ from jinja2 import Template
+
+ t = Template(template, trim_blocks=True, lstrip_blocks=True)
+ print(t.render(**kwargs))
+
+
+def lightrag_prompt(template, task_desc_str, input_str, tools=None):
+ from lightrag.core.prompt_builder import Prompt
+
+ prompt = Prompt(
+ template=template,
+ prompt_kwargs={
+ "task_desc_str": task_desc_str,
+ "tools": tools,
+ },
+ )
+ print(prompt)
+ print(prompt(input_str=input_str))
+
+ saved_prompt = prompt.to_dict()
+ restored_prompt = Prompt.from_dict(saved_prompt)
+ print(
+ restored_prompt == prompt
+ ) # False as the jinja2 template can not be serialized, but we recreated the template from the string at the time of restoration, so it works the same
+ print(restored_prompt)
+
+
+def lightrag_default_prompt():
+ from lightrag.core.prompt_builder import Prompt
+
+ prompt = Prompt()
+ input_str = "What is the capital of France?"
+ output = prompt(input_str=input_str)
+ print(output)
+
+
+if __name__ == "__main__":
+
+ task_desc_str = "You are a helpful assitant"
+ input_str = "What is the capital of France?"
+ tools = ["google", "wikipedia", "wikidata"]
+ template = r"""{{ task_desc_str }}
+{# tools #}
+{% if tools %}
+
+{% for tool in tools %}
+{{loop.index}}. {{ tool }}
+{% endfor %}
+
+{% endif %}
+User: {{ input_str }}"""
+ python_str_format_example(task_desc_str, input_str)
+ jinja2_template_example(template, task_desc_str=task_desc_str, input_str=input_str)
+ jinja2_template_example(
+ template, task_desc_str=task_desc_str, input_str=input_str, tools=tools
+ )
+ lightrag_prompt(
+ template, task_desc_str=task_desc_str, input_str=input_str, tools=tools
+ )
+
+ lightrag_default_prompt()
diff --git a/docs/source/_static/database.png b/docs/source/_static/database.png
deleted file mode 100644
index b7903a89..00000000
Binary files a/docs/source/_static/database.png and /dev/null differ
diff --git a/docs/source/apis/components/index.rst b/docs/source/apis/components/index.rst
index 3a311617..24890fa4 100644
--- a/docs/source/apis/components/index.rst
+++ b/docs/source/apis/components/index.rst
@@ -1,3 +1,5 @@
+.. _apis-components:
+
Components
==============
@@ -10,9 +12,9 @@ Overview
components.agent
components.model_client
components.data_process
-
+
.. components.reasoning
-
+
components.retriever
components.output_parsers
@@ -65,4 +67,3 @@ Retrievers
:maxdepth: 1
components.retriever
-
diff --git a/docs/source/apis/core/index.rst b/docs/source/apis/core/index.rst
index dc5dc194..c9f7399b 100644
--- a/docs/source/apis/core/index.rst
+++ b/docs/source/apis/core/index.rst
@@ -1,3 +1,5 @@
+.. _apis-core:
+
Core
===================
@@ -7,7 +9,7 @@ Overview
----------
.. autosummary::
- core.base_data_class
+ core.base_data_class
core.component
core.db
core.default_prompt_template
diff --git a/docs/source/apis/eval/index.rst b/docs/source/apis/eval/index.rst
index 966c01a1..d3b09e39 100644
--- a/docs/source/apis/eval/index.rst
+++ b/docs/source/apis/eval/index.rst
@@ -1,3 +1,5 @@
+.. _apis-eval:
+
Evaluation
==============
diff --git a/docs/source/apis/optim/index.rst b/docs/source/apis/optim/index.rst
index 74894349..3e2f23d8 100644
--- a/docs/source/apis/optim/index.rst
+++ b/docs/source/apis/optim/index.rst
@@ -1,3 +1,5 @@
+.. _apis-optim:
+
.. Optimizer
.. ==============
@@ -22,4 +24,4 @@ Optimizer
optim.sampler
optim.few_shot_optimizer
optim.llm_augment
- optim.llm_optimizer
\ No newline at end of file
+ optim.llm_optimizer
diff --git a/docs/source/apis/tracing/index.rst b/docs/source/apis/tracing/index.rst
index 66ffceef..7a266ecd 100644
--- a/docs/source/apis/tracing/index.rst
+++ b/docs/source/apis/tracing/index.rst
@@ -1,3 +1,5 @@
+.. _apis-tracing:
+
Tracing
==============
@@ -22,4 +24,4 @@ Loggers
:maxdepth: 1
tracing.generator_state_logger
- tracing.generator_call_logger
\ No newline at end of file
+ tracing.generator_call_logger
diff --git a/docs/source/apis/utils/index.rst b/docs/source/apis/utils/index.rst
index 4f13a5c5..fb339773 100644
--- a/docs/source/apis/utils/index.rst
+++ b/docs/source/apis/utils/index.rst
@@ -1,3 +1,5 @@
+.. _apis-utils:
+
Utils
=============================
@@ -31,4 +33,3 @@ Setup_env
:maxdepth: 1
utils.setup_env
-
diff --git a/docs/source/developer_notes/index.rst b/docs/source/developer_notes/index.rst
index 7fca9427..463b03a5 100644
--- a/docs/source/developer_notes/index.rst
+++ b/docs/source/developer_notes/index.rst
@@ -4,7 +4,7 @@
Tutorials
=============================
-*Why and How Each Part works*
+.. *Why and How Each Part works*
Learn the `why` and `how-to` (customize and integrate) behind each core part within the `LightRAG` library.
These are our most important tutorials before you move ahead to build use cases (LLM applications) end to end.
@@ -47,7 +47,8 @@ Building
-------------------
Base classes
~~~~~~~~~~~~~~~~~~~~~~
-Code path: ``lightrag.core``.
+Code path: :ref:`lightrag.core `.
+
.. list-table::
:widths: 20 80
@@ -56,9 +57,9 @@ Code path: ``lightrag.core``.
* - Base Class
- Description
* - :doc:`component`
- - Similar to ``Module`` in `PyTorch`, it standardizes the interface of all components with `call`, `acall`, and `__call__` methods, handles states, and serialization. Components can be easily chained togehter via `Sequential` for now.
+ - The building block for task pipeline. It standardizes the interface of all components with `call`, `acall`, and `__call__` methods, handles state serialization, nested components, and parameters for optimization. Components can be easily chained together via ``Sequential``.
* - :doc:`base_data_class`
- - Leverages the ``dataclasses`` module in Python to ease the data interaction with prompt and serialization.
+ - The base class for data. It eases the data interaction with LLMs for both prompt formatting and output parsing.
@@ -79,10 +80,10 @@ RAG components
^^^^^^^^^^^^^^^^^^^
-Code path: ``lightrag.core``. For abstract classes:
+Code path: :ref:`lightrag.core`. For abstract classes:
-- ``ModelClient``: the functional subclass is in ``lightrag.components.model_client``.
-- ``Retriever``: the functional subclass is in ``lightrag.components.retriever``. It works hand-in-hand with the ``LocalDB`` and Cloud DB in ``lightrag.database``.
+- ``ModelClient``: the functional subclass is in :ref:`lightrag.components.model_client`.
+- ``Retriever``: the functional subclass is in :ref:`lightrag.components.retriever`.
.. list-table::
@@ -92,11 +93,13 @@ Code path: ``lightrag.core``. For abstract classes:
* - Part
- Description
* - :doc:`prompt`
- - Built on ``jinja2``, it programmablly and flexibly format prompt(text) as **input to the generator**.
+ - Built on `jinja2`, it programmatically and flexibly formats prompts as input to the generator.
* - :doc:`model_client`
- ``ModelClient`` is the protocol and base class for LightRAG to **integrate all models**, either APIs or local, LLMs or Embedding models or any others.
* - :doc:`generator`
- The **center component** that orchestrates the model client(LLMs in particular), prompt, and output processors for format parsing or any post processing.
+ * - :doc:`output_parsers`
+ - The component that parses the output string to structured data.
* - :doc:`embedder`
- The component that orchestrates model client (Embedding models in particular) and output processors.
* - :doc:`retriever`
@@ -133,6 +136,7 @@ Components work on a sequence of ``Document`` and return a sequence of ``Documen
prompt
model_client
generator
+ output_parsers
embedder
retriever
text_splitter
diff --git a/docs/source/developer_notes/output_parsers.rst b/docs/source/developer_notes/output_parsers.rst
new file mode 100644
index 00000000..dc1f8e4c
--- /dev/null
+++ b/docs/source/developer_notes/output_parsers.rst
@@ -0,0 +1,2 @@
+OutputParser
+=============
diff --git a/docs/source/developer_notes/prompt.rst b/docs/source/developer_notes/prompt.rst
index 2c73bc85..c9a1e888 100644
--- a/docs/source/developer_notes/prompt.rst
+++ b/docs/source/developer_notes/prompt.rst
@@ -5,167 +5,244 @@ Prompt
`Li Yin `_
-We strick to maximize developers' control towards the final experience and performance, simplify the development process, and minimize the token consumption.
+Context
+----------------
-For the major chat models, we eventually will only send two messages to the model: the system message and the user message. The user message is simple,
-often you have a message `{'role': 'user', 'content': 'Hello, how are you?'}`. The system message is more complex, it contains the task description, tools, examples, chat history, context, and
-intermediate step history from agents.
+The prompt refers to the text input to the LLM models.
+When sent to an LLM, the model uses the prompt to auto-regressively generate the next tokens, continuing the process until it reaches a specified stopping criterion.
+The prompt itself plays a crucial role in the performance of the desired tasks.
+Researchers often use `special tokens` [1]_ to separate different sections of the prompt, such as the system message, user message, and assistant message.
+Ideally, developers should format this prompt with special tokens specific to the model's at training time.
+However, many proprietary APIs did not disclose their special tokens, and requires users to send them in the forms of messages of different roles.
-Prompt template
----------------------
+Design
+----------------
-Our `DEFAULT_LIGHTRAG_SYSTEM_PROMPT` templates the system prompt with 7 important sections. We leverage `jinjia2` template for **programmable prompt** right along with string.
+`LightRAG` seeks to maximize developers' control over the prompt.
+Thus, in most cases we help developers gather together different sections and form them into one prompt.
+This prompt will then be send to the LLM as a single message.
+The default role of the message we use is `system`.
+Though it is not a special token, we use ```` to represent the system message in the prompt, which works quite well.
-The default template comes with 7 variables: `task_desc_str`, `output_format_str`, `tools_str`, `examples_str`, `chat_history_str`, `context_str`, and `steps_str`.
+.. code-block:: python
+
+ simple_prompt = r""" You are a helpful assistant. User: What can you help me with?"""
-A jinjia2 template will rendered with :ref:`Prompt` class. If some fields being empty, that section will be empty in the final prompt string.
+If it is `Llama3` model, the final text sent to the model for tokenization will be:
.. code-block:: python
- :linenos:
- DEFAULT_LIGHTRAG_SYSTEM_PROMPT = r"""{# task desc #}
- {% if task_desc_str %}
- {{task_desc_str}}
- {% endif %}
- {# tools #}
- {% if tools_str %}
-
- {{tools_str}}
-
- {% endif %}
- {# example #}
- {% if examples_str %}
-
- {{examples_str}}
-
- {% endif %}
- {# chat history #}
- {% if chat_history_str %}
-
- {{chat_history_str}}
-
- {% endif %}
- {#contex#}
- {% if context_str %}
-
- {{context_str}}
-
- {% endif %}
- {# steps #}
- {% if steps_str %}
-
- {{steps_str}}
-
- {% endif %}
- """
-
-Across our library, here our advanced features:
-
-- Various output formats where the `output_format_str` variable is used to pass the output format to the model.
-
-- Few-shot and Many-shots In-context Learning (ICL) where the `examples_str` variable is used to pass the examples to the model.
-
-- Tools/Function Calls where the `tools_str` variable is used to pass the tools to the model.
-
-- Memory where the `chat_history_str` variable is used to pass the memory to the model.
-
-- Retrieval augmented generation(RAG) where the `context_str`` variable is used to pass the retrieved context.
-
-- Agent with multiple step planning and replanning capabilities, where the `steps_str` variable is used to pass the previous steps to the model.
-
-**Note: this means in default our out-of-box components would not support API providers's tools/function calls as we only send the system and user messages to the model.
-But it should not stop you from implementing them yourself.**
+ final_prompt = r"""<|begin_of_text|><|start_header_id|>system<|end_header_id|>
+ {{simple_prompt}} <|eot_id|>"""
-Prompt class
----------------------
-We designed a :ref:`Prompt` class to render the `template` with the variables to string as the final system prompt. In the simplest case, the string is empty and we will only send
-a user message to the model. And in most cases, you want to add at least the `task_desc_str` to the system message.
+And the LLM will return the following text:
+
+.. code-block:: python
+
+ prediction = r"""<|start_header_id|>assistant<|end_header_id|> You can ask me anything you want. <|eot_id|><|end_of_text|>"""
+
+Data Flow in LLM applications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. figure:: /_static/images/LightRAG_dataflow.png
+ :align: center
+ :alt: Data Flow in LLM applications
+ :width: 620px
+
+ Data flow in LLM applications
+
+Look at the most complicated case: We will have user query, retrieved context, task description, definition of tools, few-shot examples, past conversation history, step history from the agent, and the output format specification.
+All these different parts need to be formatted into a single prompt.
+We have to do all this with flexiblity and also easy for developers to read.
-The cool thing about our `Prompt` system is how flexible it can be. If you need to put another `template` for say `task_desc_str`, you can do that using the `Prompt` class.
-For example, your task is to instruct the llm to choose `top_k` from the given choices, you can define a new template like this:
+
+Why Jinja2?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To format the prompt, you can use any of Python's native string formatting.
.. code-block:: python
:linenos:
- from core.prompt_builder import Prompt
+ # percent(%) formatting
+ print("%s User: %s" % (task_desc_str, input_str))
- task_desc_template = r"""
- Choose the top {{top_k}} from the following choices: {{choices}}
- """
- top_k = 3
- choices = ['apple', 'banana', 'orange', 'grape']
- task_desc_prompt = Prompt(template=task_desc_template, preset_prompt_kwargs={'top_k': top_k, 'choices': choices})
- task_desc_str = task_desc_prompt.call()
- prompt = Prompt(preset_prompt_kwargs={'task_desc_str': task_desc_str})
- prompt.print_prompt()
+ # format() method with kwargs
+ print(
+ "{task_desc_str} User: {input_str}".format(
+ task_desc_str=task_desc_str, input_str=input_str
+ )
+ )
-The output would be:
+ # f-string
+ print(f"{task_desc_str} User: {input_str}")
-.. code-block:: xml
- :linenos:
+ # Templates
+ from string import Template
- Choose the top 3 from the following choices: ['apple', 'banana', 'orange', 'grape']
+ t = Template("$task_desc_str User: $input_str")
+ print(t.substitute(task_desc_str=task_desc_str, input_str=input_str))
+We opted for `Jinja2` [1]_ as the templating engine for the prompt.
+Besides of the placeholders using ``{{}}`` for key-word arguments, Jinja2 also allow users to write code similar to Python syntax.
+This includes conditionals, loops, filters, and even comments that is lacked from Python's native string formatting.
+Here is one example of using `Jinja2` to format the prompt:
+.. code-block:: python
+
+ def jinja2_template_example(**kwargs):
+ from jinja2 import Template
-Prompt and Special Tokens context
-----------------------------------
+ template = r"""{{ task_desc_str }}
+ {# tools #}
+ {% if tools %}
+
+ {% for tool in tools %}
+ {{loop.index}}. {{ tool }}
+ {% endfor %}
+
+ {% endif %}
+ User: {{ input_str }}"""
+ t = Template(template, trim_blocks=True, lstrip_blocks=True)
+ print(t.render(**kwargs))
+Let's call it with and without tools:
-Each section other than `task_desc_str` is encapulated in a special token. Different model can have different special tokens.
-Here is one example of `Llama3 Documentation `_ prompts formatted with special tokens:
+.. code-block:: python
-input string to the LLM model and minimize the token consumption.
-We enable advanced features without relying on API provider's prompt manipulation such as `OpenAI`'s tools or assistant APIs.
+ jinja2_template_example(task_desc_str=task_desc_str, input_str=input_str)
+ jinja2_template_example(
+ task_desc_str=task_desc_str, input_str=input_str, tools=tools
+ )
+
+The printout would be:
.. code-block::
- :linenos:
- <|begin_of_text|><|start_header_id|>system<|end_header_id|>
+ You are a helpful assitant
+ User: What is the capital of France?
+
+And with tools:
+
+.. code-block::
+
+ You are a helpful assitant
+
+ 1. google
+ 2. wikipedia
+ 3. wikidata
+
+ User: What is the capital of France?
+
+We can see how easy and flexible to programmatically format the prompt with `Jinja2`.
+
- You are a helpful AI assistant for travel tips and recommendations<|eot_id|>
- <|start_header_id|>user<|end_header_id|>
- What can you help me with?<|eot_id|>
+Prompt class
+----------------
+
- <|start_header_id|>assistant<|end_header_id|>
+We created our :class:`Prompt Component` to render the prompt with the string ``template`` and ``prompt_kwargs``.
+It is a rather simple component, but it is rather handy.
+Let's use the same template as above:
+.. code-block:: python
+ from lightrag.core.prompt_builder import Prompt
+ prompt = Prompt(
+ template=template,
+ prompt_kwargs={
+ "task_desc_str": task_desc_str,
+ "tools": tools,
+ },
+ )
+ print(prompt)
+ print(prompt(input_str=input_str)) # takes the rest arguments in keyword arguments
-Here is how you customize a new prompt:
+The ``Prompt`` class allow us to preset some of the prompt arguments at initialization, and then we can call the prompt with the rest of the arguments.
+Also, by subclassing ``Component``, we get to easily visualize this component with ``print``.
+Here is the output:
+
+.. code-block::
+
+ Prompt(
+ template: {{ task_desc_str }}
+ {# tools #}
+ {% if tools %}
+
+ {% for tool in tools %}
+ {{loop.index}}. {{ tool }}
+ {% endfor %}
+
+ {% endif %}
+ User: {{ input_str }}, prompt_kwargs: {'task_desc_str': 'You are a helpful assitant', 'tools': ['google', 'wikipedia', 'wikidata']}, prompt_variables: ['input_str', 'tools', 'task_desc_str']
+ )
+
+As all components, you can use ``to_dict`` and ``from_dict`` to serialize and deserialize the component.
+
+Default Prompt Template
+-------------------------
+In default, ``Prompt`` class uses the :const:`DEFAULT_LIGHTRAG_SYSTEM_PROMPT` as its string template if no template is provided.
+This default template will allow you conditionally passing seven important variables designed from the data flow diagram above.
+These varaibles are:
.. code-block:: python
- :linenos:
- from core.prompt_builder import Prompt
+ LIGHTRAG_DEFAULT_PROMPT_ARGS = [
+ "task_desc_str", # task description
+ "output_format_str", # output format of the task
+ "tools_str", # tools used in the task
+ "examples_str", # examples of the task
+ "chat_history_str", # chat history of the user
+ "context_str", # context of the user query
+ "steps_str", # used in agent steps
+ "input_str", # user query or input
+ ]
+
+Now, let's see the minimum case where we only have the user query:
- new_template = r"""
- <|begin_of_text|><|start_header_id|>system<|end_header_id|>
- {{task_desc_str}}
- Your context: {{context_str}} <|eot_id|>
+.. code-block:: python
+
+ prompt = Prompt()
+ output = prompt(input_str=input_str)
+ print(output)
+
+The output will be bare minimum with only the user query and a prefix for assistant to respond:
+
+.. code-block::
+
+
+ What is the capital of France?
+
+ You:
- <|start_header_id|>user<|end_header_id|>
- {{query_str}}<|eot_id|>
+.. note::
- <|start_header_id|>assistant<|end_header_id|>
- """
+ We barely need to use the raw ``Prompt`` class directly as it is orchestrated by the ``Generator`` component.
- prompt = Prompt(template=new_template)
-Prompt Engineering experience
--------------------------------
-There is not robust prompt, and it is one of the most sensitive creatures in the AI world.
-Here are some tips:
-- Even the output format matters, the order of your output fields, the formating.
-Output yaml or json format can lead to different performance. We have better luck with yaml format.
-- Few-shot works so well in some case, but it can lead to regression in some cases.
-- It is not fun to be a prompt engineer! But what can we do for now.
+.. Prompt Engineering experience
+.. -------------------------------
+.. There is no robust prompt, and it is one of the most sensitive creatures in the AI world.
+.. Here are some tips:
+.. - Even the output format matters, the order of your output fields, the formating. Output yaml or json format can lead to different performance. We have better luck with yaml format.
+.. - Few-shot works so well in some case, but it can lead to regression in some cases.
+.. - It is not fun to be a prompt engineer! But what can we do for now.
+
+.. admonition:: References
+ :class: highlight
+
+ .. [1] Jinja2: https://jinja.palletsprojects.com/en/3.1.x/
+ .. [2] Llama3 special tokens: https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-3/
+
+.. admonition:: API References
+ :class: highlight
-Resources:
-1. `Jinja2`:
+ - :class:`core.prompt_builder.Prompt`
+ - :const:`core.default_prompt_template.DEFAULT_LIGHTRAG_SYSTEM_PROMPT`
diff --git a/docs/source/insert_labels.py b/docs/source/insert_labels.py
index bdf5f036..324c10af 100644
--- a/docs/source/insert_labels.py
+++ b/docs/source/insert_labels.py
@@ -4,17 +4,21 @@
def add_reference_labels(directory: str):
try:
for filename in os.listdir(directory):
- if filename.endswith(".rst") and "index" not in filename:
+ if filename.endswith(".rst"):
+ if filename == "index.rst":
+ module_label = "-".join(directory.split("/")[-2:])
+ else:
+ module_label = filename.replace(".rst", "").replace(".", "-")
filepath = os.path.join(directory, filename)
with open(filepath, "r+") as file:
content = file.read()
file.seek(0, 0)
- module_label = filename.replace(".rst", "").replace(".", "-")
+ # module_label = filename.replace(".rst", "").replace(".", "-")
if module_label not in content:
label_line = f".. _{module_label}:\n\n"
file.write(label_line + content)
- except:
- print(f"directory {directory} not exists")
+ except Exception as e:
+ print(f"directory {directory} not exists: {e}")
if __name__ == "__main__":
diff --git a/images/LightRAG-logo-circle.png b/images/LightRAG-logo-circle.png
deleted file mode 100644
index 899dba0c..00000000
Binary files a/images/LightRAG-logo-circle.png and /dev/null differ
diff --git a/images/LightRAG-logo-doc.jpeg b/images/LightRAG-logo-doc.jpeg
deleted file mode 100644
index f8c64904..00000000
Binary files a/images/LightRAG-logo-doc.jpeg and /dev/null differ
diff --git a/images/LightRAG-logo.jpg b/images/LightRAG-logo.jpg
deleted file mode 100644
index 13ec4b56..00000000
Binary files a/images/LightRAG-logo.jpg and /dev/null differ
diff --git a/images/LightRAG_dataflow.png b/images/LightRAG_dataflow.png
deleted file mode 100644
index b385553c..00000000
Binary files a/images/LightRAG_dataflow.png and /dev/null differ
diff --git a/images/lightrag_structure.png b/images/lightrag_structure.png
deleted file mode 100644
index cf40969b..00000000
Binary files a/images/lightrag_structure.png and /dev/null differ
diff --git a/lightrag/core/prompt_builder.py b/lightrag/core/prompt_builder.py
index b529de86..75396f4d 100644
--- a/lightrag/core/prompt_builder.py
+++ b/lightrag/core/prompt_builder.py
@@ -33,7 +33,7 @@ def get_jinja2_environment():
class Prompt(Component):
- __doc__ = r"""A component that renders a text string from a template using Jinja2 templates.
+ __doc__ = r"""Renders a text string(prompt) from a Jinja2 template string.
In default, we use the :ref:`DEFAULT_LIGHTRAG_SYSTEM_PROMPT` as the template.
@@ -66,7 +66,6 @@ class Prompt(Component):
def __init__(
self,
- *,
template: Optional[str] = None,
prompt_kwargs: Optional[Dict] = {},
):
@@ -92,7 +91,7 @@ def __create_jinja2_template(self):
raise ValueError(f"Invalid Jinja2 template: {e}")
def update_prompt_kwargs(self, **kwargs):
- r"""Update the preset prompt kwargs after Prompt is initialized."""
+ r"""Update the initial prompt kwargs after Prompt is initialized."""
self.prompt_kwargs.update(kwargs)
def get_prompt_variables(self) -> List[str]:
@@ -109,7 +108,7 @@ def _find_template_variables(self, template_str: str):
return meta.find_undeclared_variables(parsed_content)
def compose_prompt_kwargs(self, **kwargs) -> Dict:
- r"""Compose the final prompt kwargs by combining the preset_prompt_kwargs and the provided kwargs."""
+ r"""Compose the final prompt kwargs by combining the initial and the provided kwargs at runtime."""
composed_kwargs = {key: None for key in self.prompt_variables}
if self.prompt_kwargs:
composed_kwargs.update(self.prompt_kwargs)
@@ -141,7 +140,7 @@ def print_prompt(self, **kwargs):
def call(self, **kwargs) -> str:
"""
- Renders the prompt template with the provided variables.
+ Renders the prompt template with keyword arguments.
"""
try:
pass_kwargs = self.compose_prompt_kwargs(**kwargs)
@@ -175,39 +174,3 @@ def to_dict(self) -> Dict[str, Any]:
exclude = ["jinja2_template"] # unserializable object
output = super().to_dict(exclude=exclude)
return output
-
-
-# if __name__ == "__main__":
-# import logging
-
-# logging.basicConfig(level=logging.DEBUG)
-# prompt = Prompt(
-# preset_prompt_kwargs={"task_desc_str": "You are a helpful assistant."}
-# )
-# print(prompt)
-# prompt.print_prompt_template()
-# prompt.print_prompt(context_str="This is a context string.")
-# prompt.call(context_str="This is a context string.")
-# states = prompt.state_dict()
-# print(f"states: {states}")
-# named_params = prompt.named_parameters()
-# print(f"named_params: {named_params}")
-# for name, param in named_params:
-# print(f"{name}: {param}")
-
-# # get dict of prompt
-# prompt_dict = prompt.to_dict()
-# print(f"prompt_dict: {prompt_dict}")
-# prompt_state = prompt.state_dict()
-# print(f"prompt_state: {prompt_state}")
-
-# EXAMPLES_TEMPLATE = r"""
-# {% if examples %}
-# {% for example in examples %}
-# {{loop.index}}. {{example}}
-# {% endfor %}
-# {% endif %}
-# """
-# examples_prompt = Prompt(template=EXAMPLES_TEMPLATE)
-# examples_str = examples_prompt.call(examples=["Example 1", "Example 2"])
-# prompt.print_prompt(examples_str=examples_str)