1. Instantiate Clients
Instantiate Clients for Freeplay and your LLM Provider2. Fetch Prompt Template
Fetch prompt template from Freeplay3. Format Prompt
format prompt including input variables and history4. Call LLM
Call your LLM provider, history will be merged into your prompt and ready to pass through5. Record Interaction
Record the interaction to Freeplay6. Manage history
Determine what to include in conversation history over each turn. Append the select messages to an arrayExamples
import json
import os
import time
from copy import deepcopy
from typing import Optional
import boto3
from anthropic import Anthropic, NotGiven
from openai import OpenAI
from freeplay import Freeplay, RecordPayload, CallInfo, SessionInfo, TraceInfo
fp_client = Freeplay(
freeplay_api_key=os.environ['FREEPLAY_API_KEY'],
api_base=f"{os.environ['FREEPLAY_API_URL']}/api"
)
project_id = os.environ['FREEPLAY_PROJECT_ID']
environment = 'dev'
anthropic_client = Anthropic(
api_key=os.environ.get("ANTHROPIC_API_KEY")
)
articles = [
"george washington was the first president of the united states",
"the sky is blue",
"the earth is round",
""
]
questions = [
"who was the first president of the united states?",
"what color is the sky?",
"what shape is the earth?",
"repeat the first question and answer"
]
input_pairs = list(zip(articles, questions))
template_prompt = fp_client.prompts.get(
project_id=project_id,
template_name='History-Basics',
environment=environment
)
def call_and_record(
project_id: str,
template_name: str,
env: str,
history: list,
input_variables: dict,
session_info: SessionInfo,
trace_info: Optional[TraceInfo] = None
) -> dict:
formatted_prompt = fp_client.prompts.get_formatted(
project_id=project_id,
template_name=template_name,
environment=env,
variables=input_variables,
history=history,
)
start = time.time()
completion = anthropic_client.messages.create(
system=formatted_prompt.system_content or NotGiven(),
messages=formatted_prompt.llm_prompt,
model=formatted_prompt.prompt_info.model,
**formatted_prompt.prompt_info.model_parameters
)
end = time.time()
llm_response = completion.content[0].text
print("Completion: %s" % llm_response)
assistant_response = {'role': 'assistant', 'content': llm_response}
all_messages = formatted_prompt.all_messages(new_message=assistant_response)
call_info = CallInfo.from_prompt_info(formatted_prompt.prompt_info, start, end)
record_response = fp_client.recordings.create(
RecordPayload(
all_messages=all_messages,
session_info=session_info,
inputs=input_variables,
prompt_info=formatted_prompt.prompt_info,
call_info=call_info,
trace_info=trace_info
)
)
return {'completion_id': record_response.completion_id,
'llm_response': assistant_response,
"all_messages": all_messages}
session = fp_client.sessions.create()
history = []
for inputs in input_pairs:
input_vars = {'question': inputs[1], 'article': inputs[0]}
record_response = call_and_record(
project_id=project_id,
template_name='History-QA',
env=environment,
history=history,
input_variables=input_vars,
session_info=session.session_info,
)
history = [msg for msg in record_response['all_messages'] if msg['role'] != 'system']
import Freeplay, {getCallInfo, getSessionInfo} from "freeplay";
import Anthropic from "@anthropic-ai/sdk";
const projectId = process.env['FREEPLAY_PROJECT_ID'];
const environment = 'dev';
const templateName = "History-QA";
const fpClient = new Freeplay({
freeplayApiKey: process.env["FREEPLAY_API_KEY"],
baseUrl: `${process.env["FREEPLAY_API_URL"]}/api`,
});
const anthropicClient = new Anthropic({apiKey: process.env['ANTHROPIC_API_KEY']})
async function call(
projectId,
templateName,
environment,
input_variables,
history,
session_info,
trace_info
){
let formattedPrompt = await fpClient.prompts.getFormatted({
projectId,
templateName,
environment,
variables: input_variables,
history: history
});
console.log("Prompt", formattedPrompt.llmPrompt);
let start = new Date();
const llmResponse = await anthropicClient.messages.create(
{
model: formattedPrompt.promptInfo.model,
messages: formattedPrompt.llmPrompt,
system: formattedPrompt.systemContent,
...formattedPrompt.promptInfo.modelParameters
}
);
let end = new Date();
const llmResponseText = llmResponse.content[0].text;
let messages = formattedPrompt.allMessages(
{
content: llmResponseText,
role: 'Assistant'
});
const completionResponse = await fpClient.recordings.create(
{
projectId,
allMessages: messages,
inputs: input_variables,
sessionInfo: session_info,
promptVersionInfo: formattedPrompt.promptInfo,
callInfo: getCallInfo(formattedPrompt.promptInfo, start, end),
traceInfo: trace_info
}
)
return {completionId: completionResponse.completionId, userMessages: formattedPrompt.llmPrompt, llmResponseText: llmResponseText};
}
const articles = [
"george washington was the first president of the united states",
"the sky is blue",
"the earth is round",
""
];
const questions = [
"who was the first president of the united states?",
"what color is the sky?",
"what shape is the earth?",
"repeat the first question and answer"
];
const inputPairs = articles.map((article, index) => [article, questions[index]]);
async function main() {
const session = await fpClient.sessions.create();
const history_messages = [];
for (const [article, question] of inputPairs) {
const traceInfo = await session.createTrace(question);
const botResponse = await call(
projectId, templateName, environment,
{ question: question, article: article }, history_messages, getSessionInfo(session), traceInfo
);
// update history
history_messages.push(...botResponse.userMessages);
history_messages.push({
content: botResponse.llmResponseText,
role: 'assistant'
});
console.log("Bot response: ", botResponse.llmResponseText);
await traceInfo.recordOutput(projectId, botResponse.llmResponseText);
}
}
main().catch(console.error);
package ai.freeplay.example.kotlin
import ai.freeplay.client.thin.Freeplay
import ai.freeplay.client.thin.resources.prompts.ChatMessage
import ai.freeplay.client.thin.resources.recordings.CallInfo
import ai.freeplay.client.thin.resources.recordings.RecordInfo
import ai.freeplay.example.java.ThinExampleUtils.callAnthropic // this is a private helper function
import com.fasterxml.jackson.databind.ObjectMapper
import kotlinx.coroutines.future.await
import kotlinx.coroutines.runBlocking
private val objectMapper = ObjectMapper()
fun main(): Unit = runBlocking {
val freeplayApiKey = System.getenv("FREEPLAY_API_KEY")
val projectId = System.getenv("FREEPLAY_PROJECT_ID")
val baseUrl = System.getenv("FREEPLAY_API_URL") + "/api"
val anthropicApiKey = System.getenv("ANTHROPIC_API_KEY")
val fpClient = Freeplay(
Freeplay.Config()
.freeplayAPIKey(freeplayApiKey)
.baseUrl(baseUrl)
)
val questions = listOf(
"who was the first president of the united states?",
"what color is the sky?",
"what shape is the earth?",
"repeat the first question and answer"
)
val articles = listOf(
"george washington was the first president of the united states",
"the sky is blue",
"the earth is round",
""
)
val history = mutableListOf<ChatMessage>()
println("Getting the prompt...")
val template = fpClient.prompts()
.get(
projectId,
"History-QA",
"latest"
).await()
val sessionInfo = fpClient.sessions().create()
.customMetadata(mapOf("custom_field" to "custom_value"))
.sessionInfo
for (i in 1..questions.size){
val variables = mapOf("question" to questions[i-1], "article" to articles[i-1])
println("variables: $variables")
val formatted = template.bind(variables, history).format<List<ChatMessage>>()
println("Calling Anthropic...")
val startTime = System.currentTimeMillis()
val llmResponse = callAnthropic(
objectMapper,
anthropicApiKey,
formatted.promptInfo.model,
formatted.promptInfo.modelParameters,
formatted.formattedPrompt,
formatted.systemContent.orElse(null)
).await()
val bodyNode = objectMapper.readTree(llmResponse.body())
println("Completion: " + bodyNode.path("content").get(0).path("text").asText())
println("Recording the result")
val allMessages: List<ChatMessage> = formatted.allMessages(
ChatMessage("assistant", bodyNode.path("content").get(0).path("text").asText())
)
if (allMessages.size >= 2) {
history.add(allMessages[allMessages.size - 2])
history.add(allMessages[allMessages.size - 1])
} else if (allMessages.isNotEmpty()) {
history.addAll(allMessages)
}
val callInfo = CallInfo.from(
formatted.promptInfo,
startTime,
System.currentTimeMillis()
)
val recordResponse = fpClient.recordings().create(
RecordInfo(
projectId,
allMessages
).inputs(variables)
.sessionInfo(session.sessionInfo)
.promptVersionInfo(prompt.promptInfo)
.callInfo(callInfo)
.traceInfo(trace)
).await()
}
}

