LangChain
Mix.install(
[
:jason,
:req,
:langchain
],
config: [
langchain: [
openai_key: System.fetch_env!("LB_OPENAI_API_KEY"),
openai_org_id: System.fetch_env!("LB_OPENAI_ORG_ID")
]
]
)
# Application.put_env(:langchain, :openai_key, System.fetch_env!("LB_OPENAI_API_KEY"))
# Application.put_env(:langchain, :openai_org_id, System.fetch_env!("LB_OPENAI_ORG_ID"))
Getting Started
alias LangChain.Chains.LLMChain
alias LangChain.ChatModels.ChatOpenAI
alias LangChain.Message
sys_prompt = """
You are an elixir developer obsests with elixir. You reply to every question/greeting with elixir code.
Even if you give simple reply you will use something like IO.puts("Hi!").
"""
{:ok, updated_chain, response} =
%{llm: ChatOpenAI.new!(%{model: "gpt-3.5-turbo-0125"})}
|> LLMChain.new!()
|> LLMChain.add_message(Message.new_system!(sys_prompt))
|> LLMChain.add_message(Message.new_user!("Hello world"))
|> LLMChain.run()
{response.content, response.status}
response.content
|> String.replace(~r/```elixir/, "")
|> String.replace(~r/```/, "")
|> Code.eval_string()
Streaming response
alias LangChain.MessageDelta
callback = fn
%MessageDelta{} = data ->
# we received a piece of data
IO.write(data.content)
%Message{} = data ->
IO.puts("")
IO.puts("")
IO.inspect(data.content, label: "COMPLETED MESSAGE")
end
{:ok, _updated_chain, response} =
%{llm: ChatOpenAI.new!(%{model: "gpt-3.5-turbo-0125", stream: true})}
|> LLMChain.new!()
|> LLMChain.add_messages([
Message.new_system!("You are a helpful assistant."),
Message.new_user!("Write a haiku about the capital of the United Kingdom")
])
|> LLMChain.run(callback_fn: callback)
defmodule OllamaClient do
# 5 mins
@timeout 300_000
@url "http://localhost:11434/api/generate"
def call(model, task, system_prompt) do
prompt = "#{system_prompt}#{task}"
payload =
Jason.encode!(%{
"model" => model,
"prompt" => prompt,
"stream" => false
})
Req.post!(@url, body: payload, receive_timeout: @timeout).body["response"]
end
end
task = """
package main
import (
"fmt"
"os"
"strings"
)
func main() {
file, err := os.ReadFile("day1/input.txt")
if err != nil {
panic(err)
}
input := strings.TrimSpace(string(file))
floor := 0
for _, c := range input {
if c == '(' {
floor++
} else if c == ')' {
floor--
}
}
fmt.Println(floor)
}
"""
system_prompt = """
You are an expert programmer that writes simple, concise code and no comments or explanation.
Given this golang program write a .cpp version that it reads its input from a file "input.txt" and solve the following task.
The program should print the answer on the stdout and can be run `/usr/bin/c++ solution.cpp`.
Ensure all functions or variables are declared before use. If a function is used before its definition, declare it at the beginning of your code or in a header file.
Always insert a space between consecutive right angle brackets in template declarations to ensure compatibility with older C++ standards. For example, use std::vector > instead of std::vector>.
Use appropriate constructors for non-aggregate types like std::vector or std::unordered_map instead of brace initialization when not directly supported.
Include the correct header for the function you are trying to use. For std::accumulate, include at the beginning of your file.
Golang Task:
"""
OllamaClient.call("qwen:14b-chat", task, system_prompt)