|
| 1 | +from typing import List |
| 2 | + |
| 3 | +from langflow.custom import Component |
| 4 | +from langflow.inputs import StrInput, SecretStrInput, DefaultPromptField |
| 5 | +from langflow.io import Output |
| 6 | +from langflow.schema.message import Message |
| 7 | + |
| 8 | + |
| 9 | +import re |
| 10 | + |
| 11 | + |
| 12 | +class LangChainHubPromptComponent(Component): |
| 13 | + display_name: str = "LangChain Hub Prompt Component" |
| 14 | + description: str = "Prompt Component that uses LangChain Hub prompts" |
| 15 | + beta = True |
| 16 | + icon = "prompts" |
| 17 | + trace_type = "prompt" |
| 18 | + name = "LangChain Hub Prompt" |
| 19 | + |
| 20 | + inputs = [ |
| 21 | + SecretStrInput( |
| 22 | + name="langchain_api_key", |
| 23 | + display_name="Your LangChain API Key", |
| 24 | + info="The LangChain API Key to use.", |
| 25 | + ), |
| 26 | + StrInput( |
| 27 | + name="langchain_hub_prompt", |
| 28 | + display_name="LangChain Hub Prompt", |
| 29 | + info="The LangChain Hub prompt to use.", |
| 30 | + value="efriis/my-first-prompt", |
| 31 | + refresh_button=True, |
| 32 | + ), |
| 33 | + ] |
| 34 | + |
| 35 | + outputs = [ |
| 36 | + Output(display_name="Build Prompt", name="prompt", method="build_prompt"), |
| 37 | + ] |
| 38 | + |
| 39 | + def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None): |
| 40 | + if field_name == "langchain_hub_prompt": |
| 41 | + template = self._fetch_langchain_hub_template() |
| 42 | + |
| 43 | + # Extract the messages from the prompt data |
| 44 | + prompt_template = [] |
| 45 | + for message_data in template.messages: |
| 46 | + prompt_template.append(message_data.prompt) |
| 47 | + |
| 48 | + # Regular expression to find all instances of {<string>} |
| 49 | + pattern = r"\{(.*?)\}" |
| 50 | + |
| 51 | + # Get all the custom fields |
| 52 | + custom_fields: List[str] = [] |
| 53 | + full_template = "" |
| 54 | + for message in prompt_template: |
| 55 | + # Find all matches |
| 56 | + matches = re.findall(pattern, message.template) |
| 57 | + custom_fields = custom_fields + matches |
| 58 | + |
| 59 | + # Create a string version of the full template |
| 60 | + full_template = full_template + "\n" + message.template |
| 61 | + |
| 62 | + # No need to reprocess if we have them already |
| 63 | + if all(["param_" + custom_field in build_config for custom_field in custom_fields]): |
| 64 | + return build_config |
| 65 | + |
| 66 | + # Easter egg: Show template in info popup |
| 67 | + build_config["langchain_hub_prompt"]["info"] = full_template |
| 68 | + |
| 69 | + # Remove old parameter inputs if any |
| 70 | + for key, _ in build_config.copy().items(): |
| 71 | + if key.startswith("param_"): |
| 72 | + del build_config[key] |
| 73 | + |
| 74 | + # Now create inputs for each |
| 75 | + for custom_field in custom_fields: |
| 76 | + new_parameter = DefaultPromptField( |
| 77 | + name=f"param_{custom_field}", |
| 78 | + display_name=custom_field, |
| 79 | + info="Fill in the value for {" + custom_field + "}", |
| 80 | + ).to_dict() |
| 81 | + |
| 82 | + build_config[f"param_{custom_field}"] = new_parameter |
| 83 | + |
| 84 | + return build_config |
| 85 | + |
| 86 | + async def build_prompt( |
| 87 | + self, |
| 88 | + ) -> Message: |
| 89 | + # Get the parameters that |
| 90 | + template = self._fetch_langchain_hub_template() # TODO: doing this twice |
| 91 | + original_params = {k[6:] if k.startswith("param_") else k: v for k, v in self._attributes.items()} |
| 92 | + prompt_value = template.invoke(original_params) |
| 93 | + |
| 94 | + original_params["template"] = prompt_value.to_string() |
| 95 | + |
| 96 | + # Now pass the filtered attributes to the function |
| 97 | + prompt = await Message.from_template_and_variables(**original_params) |
| 98 | + |
| 99 | + self.status = prompt.text |
| 100 | + |
| 101 | + return prompt |
| 102 | + |
| 103 | + def _fetch_langchain_hub_template(self): |
| 104 | + import langchain.hub |
| 105 | + |
| 106 | + # Pull the prompt from LangChain Hub |
| 107 | + prompt_data = langchain.hub.pull(self.langchain_hub_prompt, api_key=self.langchain_api_key) |
| 108 | + |
| 109 | + return prompt_data |
0 commit comments