fp/apps/bright/lib/bright/vultr_ai.ex

132 lines
3.8 KiB
Elixir

defmodule Bright.VultrAI do
require Logger
@model "mistral-7b-v0.3"
@chat_endpoint "https://api.vultrinference.com/v1/chat/completions"
@doc """
This is not in-use due to less than stellar results. Keeping for future reference.
"""
def parse_social_post(raw_text, known_platforms) do
system_prompt = """
You are a social media post parser specializing in identifying livestream invitations and the platforms they are taking place on.
Analyze the following tweet and extract relevant information according to the JSON schema provided. Your response must be **valid JSON**.
## **Rules:**
1. **Title:** Use a short, relevant snippet from the tweet that represents the livestream event. If no livestream is mentioned, set the title as an empty string (`""`).
2. **Platforms:** Identify any livestream platforms mentioned in the tweet from this predefined list:
#{known_platforms}
- If none are found, return an empty array (`[]`).
## **Expected Response Schema**
#{expected_schema(known_platforms)}
"""
user_prompt = raw_text
request(@chat_endpoint, @model, system_prompt, user_prompt)
end
def expected_schema(known_platforms) do
%{
"type" => "object",
"properties" => %{
"title" => %{
"type" => "string",
"minLength" => 0
},
"platforms" => %{
"type" => "array",
"items" => %{
"type" => "string",
"enum" => known_platforms
},
"minItems" => 0,
"uniqueItems" => true
}
},
"required" => ["title", "platforms"],
"additionalProperties" => false
}
|> Jason.encode!()
end
def request(endpoint, model, system_prompt, user_prompt) do
api_key = Application.get_env(:bright, :vultr_ai_api_key)
headers = [
{"Authorization", "Bearer #{api_key}"},
{"Content-Type", "application/json"},
{"Accept", "Application/json; Charset=utf-8"}
]
body =
%{
messages: [
%{
role: "system",
content: system_prompt
},
%{
role: "user",
content: user_prompt
}
],
model: model,
stream: false,
max_tokens: 512,
n: 1,
seed: 0,
temperature: 1,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
logprobs: false
}
|> Jason.encode!()
case(HTTPoison.post(endpoint, body, headers)) do
{:ok, %HTTPoison.Response{status_code: 200, body: response_body}} ->
Logger.info("Successful VultrAI")
parse_response(response_body)
{:ok, %HTTPoison.Response{status_code: status_code, body: error_body}} ->
Logger.error("Failed VultrAI status=#{status_code}, error=#{error_body}")
{:error, %{status: status_code, body: error_body}}
{:error, %HTTPoison.Error{reason: reason}} ->
Logger.error("VultrAI HTTP request failed, reason=#{inspect(reason)}")
{:error, reason}
end
end
defp parse_response(response_body) do
with {:ok, decoded} <- Jason.decode(response_body),
{:ok, raw_content} <- extract_content(decoded),
{:ok, parsed_content} <- Jason.decode(raw_content) do
Logger.info("Successful VultrAI response")
Logger.debug(parsed_content)
{:ok, parsed_content}
else
error ->
log_and_return_error("Failed to parse response", error)
end
end
defp extract_content(%{"choices" => [%{"message" => %{"content" => content}} | _]}) do
{:ok, content}
end
defp extract_content(_), do: {:error, :invalid_response_format}
defp log_and_return_error(message, details) do
Logger.error("#{message}: #{inspect(details)}")
{:error, details}
end
end