diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b892d4..005861a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,13 @@ For convenience we recommend using this as a pre-push hook: cp presubmit.sh .git/hooks/pre-push ``` +You can run the library via the `iex` shell to run functions through it, e.g.: + +``` +iex -S mix +iex()> ProdopsEx.Artifact.get(123, "story") +``` + ## Submitting Changes 1. Find or open an Issue related to the changes you're making diff --git a/lib/prodops/artifact.ex b/lib/prodops/artifact.ex index b236ae0..0068dc6 100644 --- a/lib/prodops/artifact.ex +++ b/lib/prodops/artifact.ex @@ -1,6 +1,21 @@ defmodule ProdopsEx.Artifact do @moduledoc """ - Handles artifact operations for the ProdOps API such as retrieving artifacts for a given project, creating artifacts, refining artifacts, and deleting artifacts. + Handles artifact operations for the ProdOps API such as retrieving artifacts + for a given project, creating artifacts, refining artifacts, and deleting artifacts. + + Artifacts are any generated content, i.e. user stories, blog posts, code + snippets, etc. They are organized by `artifact_slug`s, which define what type + of content they are. Most artifact operations require specifying the + `artifact_slug`. + + They are generated by passing input into a prompt template. Inputs come from + up to three places: + - user inputs: you can specify what values these have when creating Artifacts + - document queries: semantically similar parts of documents are automatically + found within a collection of documents, and inserted into the prompt template + prior to generation, known as Retrieval-Augmented Generation (RAG) + - document attachments: an entire document, such as something uploaded by you, + is inserted into the prompt template prior to generation """ alias ProdopsEx.Client alias ProdopsEx.Config @@ -12,7 +27,7 @@ defmodule ProdopsEx.Artifact do end @doc """ - Retrieves artifacts for a given project. + Retrieves artifacts of one type based on the `artifact_slug` for a given project. ## Parameters @@ -34,7 +49,10 @@ defmodule ProdopsEx.Artifact do "content" => "You are going to be a product manager and write a BDD-style user story...", "role" => "user" }, - ... + %{ + "content" => "## Background ...", + "role" => "assistant" + } ], "content" => "## Background ...", "id" => 1, @@ -42,8 +60,7 @@ defmodule ProdopsEx.Artifact do "name" => "Artifact Name", "notes" => nil, "share_token" => nil - }, - ... + } ] } }} @@ -74,6 +91,7 @@ defmodule ProdopsEx.Artifact do iex> ProdopsEx.Artifact.create(%{ ...> prompt_template_id: 2, ...> artifact_slug: "story", + ...> project_id: 1, ...> inputs: [ ...> %{name: "Context", value: "this is a test"} ...> ], @@ -117,8 +135,28 @@ defmodule ProdopsEx.Artifact do iex> ProdopsEx.Artifact.get(1, "story") {:ok, - - } + %{ + status: "ok", + response: %{ + "artifact" => %{ + "chat_history" => [ + %{ + "content" => "some user prompt content", + "role" => "user" + }, + %{ + "content" => "some assistant response content", + "role" => "assistant" + } + ], + "id" => 123, + "manually_edited" => false, + "name" => "Some Name", + "notes" => nil, + "share_token" => nil + } + } + }} """ @spec get(integer(), String.t(), Keyword.t()) :: {:ok, map} | {:error, any} def get(artifact_id, artifact_slug, config \\ []) when is_integer(artifact_id) and is_binary(artifact_slug) do @@ -138,7 +176,7 @@ defmodule ProdopsEx.Artifact do ## Example - iex> ProdopsEx.Artifact.delete(1) + iex> ProdopsEx.Artifact.delete(1, "story") {:ok, %{status: "ok", response: %{"message" => "Artifact deleted successfully."}}} """ @@ -158,7 +196,7 @@ defmodule ProdopsEx.Artifact do ## Example - iex> ProdopsEx.Artifacts.refine_artifact(%{ + iex> ProdopsEx.Artifact.refine_artifact(%{ ...> artifact_id: 1, ...> artifact_slug: "story", ...> refine_prompt: "Refine this story" @@ -172,7 +210,8 @@ defmodule ProdopsEx.Artifact do }, Keyword.t() ) :: {:ok, map} | {:error, any} - def refine_artifact(%{artifact_slug: artifact_slug, artifact_id: artifact_id} = params, config) do + def refine_artifact(%{artifact_slug: artifact_slug, artifact_id: artifact_id} = params, config \\ []) do + config = Config.resolve_config(config) url = url(config) <> "/#{artifact_slug}/artifacts/#{artifact_id}/refine" Client.api_post(url, params, config) end @@ -187,7 +226,7 @@ defmodule ProdopsEx.Artifact do ## Example - iex> ProdopsEx.stream_refine_artifact(%{artifact_slug: "story", artifact_id: 1}, %ProdopsEx.Config{bearer_token: "your_api_key_here"}) + iex> ProdopsEx.Artifact.stream_refine_artifact(%{artifact_slug: "story", artifact_id: 1, refine_prompt: "some prompt"}) """ @spec stream_refine_artifact(map, Keyword.t()) :: {:ok, map} | {:error, any} def stream_refine_artifact(params, config \\ []) do diff --git a/lib/prodops/artifact_type.ex b/lib/prodops/artifact_type.ex index 5b18887..110b67b 100644 --- a/lib/prodops/artifact_type.ex +++ b/lib/prodops/artifact_type.ex @@ -1,6 +1,10 @@ defmodule ProdopsEx.ArtifactType do @moduledoc """ Handles artifact type operations for the ProdOps API. + + These represent types of outputs. They may be things like user stories, code + snippets, blog posts, or anything else that has been defined within the + ProdOps UI. They are used to classify generated Artifacts into groups. """ alias ProdopsEx.Client alias ProdopsEx.Config @@ -13,13 +17,21 @@ defmodule ProdopsEx.ArtifactType do ## Examples iex> ProdopsEx.ArtifactType.list() - {:ok, %{status: "ok", response: %{ "artifact_types": [ - { - "slug": "story", - "name": "Story", - "description": "This is a story" - } - ]}}} + {:ok, + %{ + status: "ok", + response: %{ + "artifact_types" => [ + %{ + "description" => "This is a story", + "name" => "Story", + "slug" => "story" + }, + ... + ] + } + } + } """ @spec list(Keyword.t()) :: {:ok, map} | {:error, any} def list(config \\ []) do diff --git a/lib/prodops/client.ex b/lib/prodops/client.ex index 6e21591..569f52c 100644 --- a/lib/prodops/client.ex +++ b/lib/prodops/client.ex @@ -1,7 +1,5 @@ defmodule ProdopsEx.Client do - @moduledoc """ - Handles HTTP client operations for interacting with the ProdOps API. - """ + @moduledoc false use HTTPoison.Base alias ProdopsEx.Stream diff --git a/lib/prodops/config.ex b/lib/prodops/config.ex index 42d665c..6ca6c7a 100644 --- a/lib/prodops/config.ex +++ b/lib/prodops/config.ex @@ -1,7 +1,5 @@ defmodule ProdopsEx.Config do - @moduledoc """ - Defines the configuration structure for interacting with the ProdOps API. - """ + @moduledoc false @definition [ api_url: [ diff --git a/lib/prodops/data_center.ex b/lib/prodops/data_center.ex index 97cbceb..fd8e16e 100644 --- a/lib/prodops/data_center.ex +++ b/lib/prodops/data_center.ex @@ -1,6 +1,14 @@ defmodule ProdopsEx.DataCenter do @moduledoc """ Handles data center operations for the ProdOps API. + + The Data Center is used for: + - uploading documents + - managing collections of documents + - connecting external Data Sources (GitHub, Jira, Notion, etc.) + + Not all of these items are currently supported by the ProdOps API, so there + is additional functionality in the UI not yet available in this SDK. """ alias ProdopsEx.Client alias ProdopsEx.Config @@ -17,7 +25,7 @@ defmodule ProdopsEx.DataCenter do ## Examples - iex> ProdopsEx.DataCenter.upload_document("/path/to/file.txt"}) + iex> ProdopsEx.DataCenter.upload_document("/path/to/file.txt") {:ok, %{status: "ok", response: %{"id" => 4}}} """ @spec upload_document(map, Keyword.t()) :: {:ok, map} | {:error, any} diff --git a/lib/prodops/project.ex b/lib/prodops/project.ex index 3605f55..7df88a6 100644 --- a/lib/prodops/project.ex +++ b/lib/prodops/project.ex @@ -1,6 +1,10 @@ defmodule ProdopsEx.Project do @moduledoc """ Handles project operations for the ProdOps API. + + A Project is used for organization, and likely represents some real-world + project, such as development of an application. Some resources can be + Project-scoped. A Team may have multiple Projects. """ alias ProdopsEx.Client alias ProdopsEx.Config @@ -21,13 +25,25 @@ defmodule ProdopsEx.Project do ## Examples iex> ProdopsEx.Project.list() - {:ok, %{status: "ok", response: %{ "projects": [ - { - "id": 1, - "name": "ProdOps", - "overview": "This is the project overview" - } - ]}}} + {:ok, + %{ + status: "ok", + response: %{ + "projects" => [ + %{ + "id" => 1, + "name" => "Project Name", + "overview" => "Project Overview" + }, + %{ + "id" => 2, + "name" => "Second Project", + "overview" => "Second Project Overview" + } + ] + } + } + } """ @spec list(Keyword.t()) :: {:ok, map} | {:error, any} def list(config \\ []) do diff --git a/lib/prodops/prompt_template.ex b/lib/prodops/prompt_template.ex index f3ea451..c2fa780 100644 --- a/lib/prodops/prompt_template.ex +++ b/lib/prodops/prompt_template.ex @@ -1,6 +1,40 @@ defmodule ProdopsEx.PromptTemplate do @moduledoc """ - Handles prompt template operations for the ProdOps API + Handles prompt template operations for the ProdOps API. + + Prompt Templates are the building blocks used for generating Artifacts. + + They are a combination of hard-coded information and variables which represent + data that can be inserted. They are the basic building block for setting up + repeatable workflows to generate Artifacts. + + They may look something like this: + + ```txt + You are a helpful assistant. A user has asked a question about company + policies, which you must answer. This is their question: + + {custom.Question} + + Use this information to answer the question: + + {query.Company Policies} + ``` + + The value `{custom.Question}` can be explicitly passed into the template + when generating a new Artifact. + + The value `{query.Company Policies}` will automatically find relevant + information by checking the value of an explicit input such as + `{custom.Question}`, and can search through all Documents or a Collection of + Documents. In this example, it might search a Collection of employee manuals, + playbooks, etc., and will calculate the most semantically similar values + between their sections and the user's question, which is the value input into + `{custom.Question}`. It will then return the relevant segments and insert them + into the prompt prior to generation. This technique is known as + Retrieval-Augmented Generation. + + For more information, see the [ProdOps.AI Prompts help page](https://help.prodops.ai/docs/category/prompts). """ alias ProdopsEx.Client alias ProdopsEx.Config @@ -16,42 +50,40 @@ defmodule ProdopsEx.PromptTemplate do - `config` (optional): a configuration map used to override default config values ## Example - - iex> ProdopsEx.PromptTemplate.list("story") - {:ok, - %{ - status: "ok", - response: %{ - "prompt_templates" => [ - { - "id": 3, - "name": "Example Prompt", - "content": "This is an example prompt template body", - "description": "This is an example prompt template", - "custom_variables": [ - { - "id": "df57af61-7741-4152-b5eb-0484b281eaaa", - "name": "Example Input", - "description": null - } - ], - "document_queries": [ - { - "id": "dcbbc393-9f00-4020-a150-ac5fa5f66095", - "name": "Example Document Query", - "query": "{custom.Example Input}", - "count": 1, - "type": "code", - "min_score": 0.75, - "collection_id": null, - "collection_ids": [] - } - ] - }, - ... - ] - } - }} + iex> ProdopsEx.PromptTemplate.list("questions") + {:ok, + %{ + status: "ok", + response: %{ + "prompt_templates" => [ + %{ + "content" => "Answer this: {custom.Question} Use these docs: {query.Documents}", + "custom_variables" => [ + %{ + "question" => "Question", + "id" => "fc4cbbe7-8f90-4c39-a8e6-582d37884f14", + "name" => "Question" + } + ], + "description" => "Answers a question using document queries", + "document_queries" => [ + %{ + "collection_id" => nil, + "collection_ids" => ~c"s", + "count" => 3, + "id" => "6c69b859-8c40-41c9-b8f9-8bb1bdf369a1", + "min_score" => 0.75, + "name" => "Documents", + "query" => "{custom.Question}", + "type" => nil + } + ], + "id" => 1, + "name" => "Question Answering" + } + ] + } + }} ## Returns The function returns a list of prompt templates for the specified artifact type. diff --git a/lib/prodops/stream.ex b/lib/prodops/stream.ex index 04a06f3..ce236cb 100644 --- a/lib/prodops/stream.ex +++ b/lib/prodops/stream.ex @@ -1,8 +1,12 @@ defmodule ProdopsEx.Stream do - @moduledoc """ - Handles streaming operations for the ProdOps API. - """ + @moduledoc false + + @doc """ + Creates a readable stream of information that another process can consume. + This is used for endpoints that support returning text as it is generated, + rather than waiting for the entire generation output to be ready. + """ def new(start_fun) do Stream.resource( start_fun, diff --git a/mix.exs b/mix.exs index d70b4c2..145974d 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,6 @@ defmodule ProdopsEx.MixProject do # Docs name: "ProdopsEx", source_url: "https://github.com/revelrylabs/prodops_ex", - homepage_url: "https://prodops.ai", docs: [ main: "readme", logo: "prodops-logo.png",