Skip to content

Commit

Permalink
add support for examples to title chain (#191)
Browse files Browse the repository at this point in the history
- added module doc with examples
- support providing examples for consistency

closes #163
  • Loading branch information
brainlid authored Nov 10, 2024
1 parent adce680 commit 2933973
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 7 deletions.
63 changes: 56 additions & 7 deletions lib/chains/text_to_title_chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,48 @@ defmodule LangChain.Chains.TextToTitleChain do
@moduledoc """
A convenience chain for turning a user's prompt text into a summarized title
for the anticipated conversation.
## Examples
A basic example that generates a title
llm = ChatOpenAI.new!(%{model: "gpt-3.5-turbo", stream: false, seed: 0})
user_text = "Let's start a new blog post about the magical properties of pineapple cookies."
%{
llm: llm,
input_text: user_text
}
|> TextToTitleChain.new!()
|> TextToTitleChain.evaluate()
#=> "Magical Properties of Pineapple Cookies Blog Post"
Want to get more consistent titles?
LLMs are pretty bad at following instructions for text length. However, we can
provide examples titles for the LLM to follow in format style and length. We
get the added benefit of getting more consistently formatted titles.
This is the same example, however now we provide other title examples to the
LLM to follow for consistency.
llm = ChatOpenAI.new!(%{model: "gpt-3.5-turbo", stream: false, seed: 0})
user_text = "Let's start a new blog post about the magical properties of
pineapple cookies."
%{
llm: llm,
input_text: user_text,
examples: [
"Blog Post: Making Delicious and Healthy Smoothies",
"System Email: Notifying Users of Planned Downtime"
]
}
|> TextToTitleChain.new!()
|> TextToTitleChain.evaluate()
#=> "Blog Post: Exploring the Magic of Pineapple Cookies"
"""
use Ecto.Schema
import Ecto.Changeset
Expand All @@ -10,7 +52,6 @@ defmodule LangChain.Chains.TextToTitleChain do
alias __MODULE__
alias LangChain.Chains.LLMChain
alias LangChain.LangChainError
alias LangChain.Message
alias LangChain.Utils
alias LangChain.Utils.ChainResult

Expand All @@ -19,12 +60,13 @@ defmodule LangChain.Chains.TextToTitleChain do
field :llm, :any, virtual: true
field :input_text, :string
field :fallback_title, :string, default: "New topic"
field :examples, {:array, :string}, default: []
field :verbose, :boolean, default: false
end

@type t :: %TextToTitleChain{}

@create_fields [:llm, :input_text, :fallback_title, :verbose]
@create_fields [:llm, :input_text, :fallback_title, :examples, :verbose]
@required_fields [:llm, :input_text]

@doc """
Expand Down Expand Up @@ -86,15 +128,22 @@ defmodule LangChain.Chains.TextToTitleChain do
def run(%TextToTitleChain{} = chain, opts \\ []) do
messages =
[
Message.new_system!(
"You expertly summarize a user's prompt into a short title or phrase to represent a conversation."
),
PromptTemplate.new!(%{
role: :system,
text: """
You expertly summarize the User Text into a short title or phrase to represent a conversation.
<%= if @examples != [] do %>Follow the style, approximate length, and format of the following examples:
<%= for example <- @examples do %>- <%= example %>
<% end %><% end %>
"""
}),
PromptTemplate.new!(%{
role: :user,
text: "Generate and return the title and nothing else. Prompt:\n<%= @input %>"
text: "Generate and return the title and nothing else. User Text:\n<%= @input %>"
})
]
|> PromptTemplate.to_messages!(%{input: chain.input_text})
|> PromptTemplate.to_messages!(%{input: chain.input_text, examples: chain.examples})

%{llm: chain.llm, verbose: chain.verbose}
|> LLMChain.new!()
Expand Down
22 changes: 22 additions & 0 deletions test/chains/text_to_title_chain_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,27 @@ defmodule LangChain.Chains.TextToTitleChainTest do

assert fallback_title == TextToTitleChain.evaluate(title_chain)
end

@tag live_call: true, live_open_ai: true
test "supports using examples", %{llm: llm, input_text: input_text} do
data = %{
llm: llm,
input_text: input_text,
fallback_title: "Default new title",
examples: [
"Blog Post: Making Delicious and Healthy Smoothies",
"System Email: Notifying Users of Planned Downtime"
],
verbose: true
}

result_title =
data
|> TextToTitleChain.new!()
|> TextToTitleChain.evaluate()

assert String.starts_with?(result_title, "Blog Post:")
assert String.contains?(result_title, "Pineapple")
end
end
end

0 comments on commit 2933973

Please sign in to comment.