Source code for lwe.backends.api.workflow.library.lwe_llm

#!/usr/bin/python

from __future__ import absolute_import, division, print_function

__metaclass__ = type

import os

from ansible.module_utils.basic import AnsibleModule

# from lwe.core import constants
from lwe.core.config import Config
from lwe import ApiBackend
import lwe.core.util as util

DOCUMENTATION = r"""
---
module: lwe_llm

short_description: Make LLM requests via LWE.

version_added: "1.0.0"

description: Make LLM requests via LWE.

options:
    message:
        description: The message to send to the model.
        required: true if template not provided
        type: str
    profile:
        description: The LWE profile to use.
        required: false
        default: 'default'
        type: str
    preset:
        description: The LWE preset to use.
        required: false
        default: None
        type: str
    preset_overrides:
        description: A dictionary of metadata and model customization overrides to apply to the preset when running the template.
        required: false
        default: None
        type: dict
    system_message:
        description: The LWE system message to use, either an alias or custom message.
        required: false
        default: None
        type: str
    max_submission_tokens:
        description: The maximum number of tokens that can be submitted. Default is max for the model.
        required: false
        default: None
        type: int
    template:
        description: An LWE template to use for constructing the prompt.
        required: true if message not provided
        default: None
        type: str
    template_vars:
        description: A dictionary of variables to substitute into the template.
        required: false
        default: None
        type: dict
    user:
        description: The LWE user to load for the execution, a user ID or username.
                     NOTE: A user must be provided to start or continue a conversation.
        required: false
        default: None (anonymous)
        type: str
    conversation_id:
        description: An existing LWE conversation to use.
                     NOTE: A conversation_id must be provided to continue a conversation.
        required: false
        default: None (anonymous, or new conversation if user is provided)
        type: int
    title:
        description: Custom title for the conversation.
                     NOTE: This is only used if a user_id is provided for a new conversation.
        required: false
        default: None
        type: str

author:
    - Chad Phillips (@thehunmonkgroup)
"""

EXAMPLES = r"""
# Simple message with default values
- name: Say hello
  lwe_llm:
    message: "Say Hello!"

# Start a new conversation with this response
- name: Start conversation
  lwe_llm:
    message: "What are the three primary colors?"
    max_submission_tokens: 512
    # User ID or username
    user: 1
    register: result

# Continue a conversation with this response
- name: Continue conversation
  lwe_llm:
    message: "Provide more detail about your previous response"
    user: 1
    conversation_id: result.conversation_id

# Use the 'mytemplate.md' template, passing in a few template variables
- name: Templated prompt
  lwe_llm:
    template: mytemplate.md
    template_vars:
        foo: bar
        baz: bang

# Use the 'test' profile, a pre-configured provider/model preset 'mypreset',
# and override some of the preset configuration.
- name: Continue conversation
  lwe_llm:
    message: "Say three things about bacon"
    system_message: "You are a bacon connoisseur"
    profile: test
    preset: mypreset
    preset_overrides:
        metadata:
            return_on_tool_call: true
        model_customizations:
            temperature: 1

"""

RETURN = r"""
response:
    description: The response from the model.
    type: str
    returned: always
conversation_id:
    description: The conversation ID if the task run is associated with a conversation, or None otherwise.
    type: int
    returned: always
user_message:
    description: Human-readable user status message for the response.
    type: str
    returned: always
"""


[docs] def run_module(): module_args = dict( message=dict(type="str", required=False), profile=dict(type="str", required=False, default="default"), # provider=dict(type='str', required=False, default='chat_openai'), # model=dict(type='str', required=False, default=constants.API_BACKEND_DEFAULT_MODEL), preset=dict(type="str", required=False), preset_overrides=dict(type="dict", required=False), system_message=dict(type="str", required=False), max_submission_tokens=dict(type="int", required=False), template=dict(type="str", required=False), template_vars=dict(type="dict", required=False), user=dict(type="raw", required=False), conversation_id=dict(type="int", required=False), title=dict(type="str", required=False), ) result = dict(changed=False, response=dict()) module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) message = module.params["message"] profile = module.params["profile"] # provider = module.params['provider'] # model = module.params['model'] preset = module.params["preset"] preset_overrides = module.params["preset_overrides"] system_message = module.params["system_message"] max_submission_tokens = module.params["max_submission_tokens"] template_name = module.params["template"] template_vars = module.params["template_vars"] or {} user = module.params["user"] try: user = int(user) except Exception: pass conversation_id = module.params["conversation_id"] title = module.params["title"] if (message is None and template_name is None) or ( message is not None and template_name is not None ): module.fail_json(msg="One and only one of 'message' or 'template' arguments must be set.") if module.check_mode: module.exit_json(**result) config_args = { "profile": profile, } config_dir = os.environ.get("LWE_CONFIG_DIR", None) data_dir = os.environ.get("LWE_DATA_DIR", None) if config_dir: config_args["config_dir"] = config_dir if data_dir: config_args["data_dir"] = data_dir config = Config(**config_args) config.load_from_file() config.set("debug.log.enabled", True) config.set("model.default_preset", preset) config.set("backend_options.default_user", user) config.set("backend_options.default_conversation_id", conversation_id) gpt = ApiBackend(config) if max_submission_tokens: gpt.set_max_submission_tokens(max_submission_tokens) gpt.set_return_only(True) gpt.log.info("[lwe_llm module]: Starting execution") overrides = { "request_overrides": {}, } if preset_overrides: overrides["request_overrides"]["preset_overrides"] = preset_overrides if system_message: overrides["request_overrides"]["system_message"] = system_message if title: overrides["request_overrides"]["title"] = title if template_name is not None: gpt.log.debug(f"[lwe_llm module]: Using template: {template_name}") success, response, user_message = gpt.template_manager.get_template_variables_substitutions( template_name ) if not success: gpt.log.error(f"[lwe_llm module]: {user_message}") module.fail_json(msg=user_message, **result) _template, _variables, substitutions = response util.merge_dicts(substitutions, template_vars) success, response, user_message = gpt.run_template_setup(template_name, substitutions) if not success: gpt.log.error(f"[lwe_llm module]: {user_message}") module.fail_json(msg=user_message, **result) message, template_overrides = response util.merge_dicts(template_overrides, overrides) gpt.log.info(f"[lwe_llm module]: Running template: {template_name}") success, response, user_message = gpt.run_template_compiled(message, template_overrides) if not success: gpt.log.error(f"[lwe_llm module]: {user_message}") module.fail_json(msg=user_message, **result) else: success, response, user_message = gpt.ask(message, **overrides) if not success or not response: result["failed"] = True message = user_message if not success: message = f"Error fetching LLM response: {user_message}" elif not response: message = f"Empty LLM response: {user_message}" gpt.log.error(f"[lwe_llm module]: {message}") module.fail_json(msg=message, **result) result["changed"] = True result["response"] = response result["conversation_id"] = gpt.conversation_id result["user_message"] = user_message gpt.log.info("[lwe_llm module]: execution completed successfully") module.exit_json(**result)
[docs] def main(): run_module()
if __name__ == "__main__": main()