Compare commits
41 Commits
657416780d
...
1456442d4e
Author | SHA1 | Date | |
---|---|---|---|
1456442d4e | |||
3185b2d7d6 | |||
6c64f21d9a | |||
6f737ad19c | |||
a8ffdc156a | |||
7a974d9764 | |||
adb61ffa59 | |||
1c7ad75fd5 | |||
613aa1a552 | |||
71833b89cd | |||
2ad93394b1 | |||
f49b772960 | |||
29d8138dc0 | |||
3756f6d9e4 | |||
41916eb7b3 | |||
3892e68251 | |||
8697284064 | |||
383d34f311 | |||
ac0e380244 | |||
c3a3cb0181 | |||
612ea90417 | |||
94508b1dbf | |||
7e002e5214 | |||
48e4dea3cf | |||
0ab552303d | |||
6ce42a77f9 | |||
2cb1a0005d | |||
ea78edf039 | |||
793aaab50e | |||
5afc9667c7 | |||
dfafc573e5 | |||
97f81a0cbb | |||
eca120cde6 | |||
12d4e495d4 | |||
d8c8262890 | |||
758f74aba5 | |||
1570c23d63 | |||
46149e0b67 | |||
c2c61e2aaa | |||
5e880d3b31 | |||
62f07dd240 |
@ -118,11 +118,18 @@ func HandleConversationReply(ctx *lmcli.Context, c *model.Conversation, persist
|
|||||||
func FormatForExternalPrompt(messages []model.Message, system bool) string {
|
func FormatForExternalPrompt(messages []model.Message, system bool) string {
|
||||||
sb := strings.Builder{}
|
sb := strings.Builder{}
|
||||||
for _, message := range messages {
|
for _, message := range messages {
|
||||||
if message.Role != model.MessageRoleUser && (message.Role != model.MessageRoleSystem || !system) {
|
if message.Content == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sb.WriteString(fmt.Sprintf("<%s>\n", message.Role.FriendlyRole()))
|
switch message.Role {
|
||||||
sb.WriteString(fmt.Sprintf("\"\"\"\n%s\n\"\"\"\n\n", message.Content))
|
case model.MessageRoleAssistant, model.MessageRoleToolCall:
|
||||||
|
sb.WriteString("Assistant:\n\n")
|
||||||
|
case model.MessageRoleUser:
|
||||||
|
sb.WriteString("User:\n\n")
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sb.WriteString(fmt.Sprintf("%s", lipgloss.NewStyle().PaddingLeft(1).Render(message.Content)))
|
||||||
}
|
}
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
@ -133,13 +140,32 @@ func GenerateTitle(ctx *lmcli.Context, c *model.Conversation) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
const header = "Generate a concise 4-5 word title for the conversation below."
|
const prompt = `Above is an excerpt from a conversation between a user and AI assistant. Please reply with a short title (no more than 8 words) that reflects the topic of the conversation, read from the user's perspective.
|
||||||
prompt := fmt.Sprintf("%s\n\n---\n\n%s", header, FormatForExternalPrompt(messages, false))
|
|
||||||
|
Example conversation:
|
||||||
|
|
||||||
|
"""
|
||||||
|
User:
|
||||||
|
|
||||||
|
Hello!
|
||||||
|
|
||||||
|
Assistant:
|
||||||
|
|
||||||
|
Hello! How may I assist you?
|
||||||
|
"""
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Title: A brief introduction
|
||||||
|
"""
|
||||||
|
`
|
||||||
|
conversation := FormatForExternalPrompt(messages, false)
|
||||||
|
|
||||||
generateRequest := []model.Message{
|
generateRequest := []model.Message{
|
||||||
{
|
{
|
||||||
Role: model.MessageRoleUser,
|
Role: model.MessageRoleUser,
|
||||||
Content: prompt,
|
Content: fmt.Sprintf("\"\"\"\n%s\n\"\"\"\n\n%s", conversation, prompt),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,12 +184,15 @@ func GenerateTitle(ctx *lmcli.Context, c *model.Conversation) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response = strings.TrimPrefix(response, "Title: ")
|
||||||
|
response = strings.Trim(response, "\"")
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowWaitAnimation prints an animated ellipses to stdout until something is
|
// ShowWaitAnimation prints an animated ellipses to stdout until something is
|
||||||
// received on the signal channel. An empty string sent to the channel to
|
// received on the signal channel. An empty string sent to the channel to
|
||||||
// noftify the caller that the animation has completed (carriage returned).
|
// notify the caller that the animation has completed (carriage returned).
|
||||||
func ShowWaitAnimation(signal chan any) {
|
func ShowWaitAnimation(signal chan any) {
|
||||||
// Save the current cursor position
|
// Save the current cursor position
|
||||||
fmt.Print("\033[s")
|
fmt.Print("\033[s")
|
||||||
|
@ -68,7 +68,7 @@ func buildRequest(params model.RequestParameters, messages []model.Message) Requ
|
|||||||
startIdx := 0
|
startIdx := 0
|
||||||
if len(messages) > 0 && messages[0].Role == model.MessageRoleSystem {
|
if len(messages) > 0 && messages[0].Role == model.MessageRoleSystem {
|
||||||
requestBody.System = messages[0].Content
|
requestBody.System = messages[0].Content
|
||||||
requestBody.Messages = requestBody.Messages[:len(messages)-1]
|
requestBody.Messages = requestBody.Messages[1:]
|
||||||
startIdx = 1
|
startIdx = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,10 @@ import (
|
|||||||
"git.mlow.ca/mlow/lmcli/pkg/lmcli/model"
|
"git.mlow.ca/mlow/lmcli/pkg/lmcli/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
const TOOL_PREAMBLE = `In this environment you have access to a set of tools which may assist you in fulfilling user requests.
|
const TOOL_PREAMBLE = `You have access to the following tools when replying.
|
||||||
|
|
||||||
You may call them like this:
|
You may call them like this:
|
||||||
|
|
||||||
<function_calls>
|
<function_calls>
|
||||||
<invoke>
|
<invoke>
|
||||||
<tool_name>$TOOL_NAME</tool_name>
|
<tool_name>$TOOL_NAME</tool_name>
|
||||||
@ -24,6 +25,14 @@ You may call them like this:
|
|||||||
|
|
||||||
Here are the tools available:`
|
Here are the tools available:`
|
||||||
|
|
||||||
|
const TOOL_PREAMBLE_FOOTER = `Recognize the utility of these tools in a broad range of different applications, and the power they give you to solve a wide range of different problems. However, ensure that the tools are used judiciously and only when clearly relevant to the user's request. Specifically:
|
||||||
|
|
||||||
|
1. Only use a tool if the user has explicitly requested or provided information that warrants its use. Do not make assumptions about files or data existing without the user mentioning them.
|
||||||
|
|
||||||
|
2. If there is ambiguity about whether using a tool is appropriate, ask a clarifying question to the user before proceeding. Confirm your understanding of their request and intent.
|
||||||
|
|
||||||
|
3. Prioritize providing direct responses and explanations based on your own knowledge and understanding. Use tools to supplement and enhance your responses when clearly applicable, but not as a default action.`
|
||||||
|
|
||||||
type XMLTools struct {
|
type XMLTools struct {
|
||||||
XMLName struct{} `xml:"tools"`
|
XMLName struct{} `xml:"tools"`
|
||||||
ToolDescriptions []XMLToolDescription `xml:"tool_description"`
|
ToolDescriptions []XMLToolDescription `xml:"tool_description"`
|
||||||
@ -151,7 +160,7 @@ func buildToolsSystemPrompt(tools []model.Tool) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not serialize []model.Tool to XMLTools")
|
panic("Could not serialize []model.Tool to XMLTools")
|
||||||
}
|
}
|
||||||
return TOOL_PREAMBLE + "\n" + xmlToolsString + "\n"
|
return TOOL_PREAMBLE + "\n\n" + xmlToolsString + "\n\n" + TOOL_PREAMBLE_FOOTER
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x XMLTools) XMLString() (string, error) {
|
func (x XMLTools) XMLString() (string, error) {
|
||||||
|
@ -244,7 +244,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
if last < 0 {
|
if last < 0 {
|
||||||
panic("Unexpected empty messages handling msgResponseEnd")
|
panic("Unexpected empty messages handling msgResponseEnd")
|
||||||
}
|
}
|
||||||
m.setMessageContents(last, strings.TrimSpace(m.messages[last].Content))
|
m.setMessageContents(last, strings.TrimSpace(string(msg)))
|
||||||
m.updateContent()
|
m.updateContent()
|
||||||
m.status = "Press ctrl+s to send"
|
m.status = "Press ctrl+s to send"
|
||||||
case msgResponseError:
|
case msgResponseError:
|
||||||
@ -786,17 +786,22 @@ func (m *model) conversationView() string {
|
|||||||
// write message heading with space for content
|
// write message heading with space for content
|
||||||
user := style.Render(icon + friendly)
|
user := style.Render(icon + friendly)
|
||||||
|
|
||||||
var saved string
|
var prefix string
|
||||||
|
var suffix string
|
||||||
|
|
||||||
|
faint := lipgloss.NewStyle().Faint(true)
|
||||||
|
if m.focus == focusMessages {
|
||||||
|
if i == m.selectedMessage {
|
||||||
|
prefix = "> "
|
||||||
|
}
|
||||||
|
suffix += faint.Render(fmt.Sprintf(" (%d/%d)", i+1, msgCnt))
|
||||||
|
}
|
||||||
|
|
||||||
if message.ID == 0 {
|
if message.ID == 0 {
|
||||||
saved = lipgloss.NewStyle().Faint(true).Render(" (not saved)")
|
suffix += faint.Render(" (not saved)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedPrefix string
|
header := lipgloss.NewStyle().PaddingLeft(1).Render(prefix + user + suffix)
|
||||||
if m.focus == focusMessages && i == m.selectedMessage {
|
|
||||||
selectedPrefix = "> "
|
|
||||||
}
|
|
||||||
|
|
||||||
header := lipgloss.NewStyle().PaddingLeft(1).Render(selectedPrefix + user + saved)
|
|
||||||
sb.WriteString(header)
|
sb.WriteString(header)
|
||||||
lineCnt += lipgloss.Height(header)
|
lineCnt += lipgloss.Height(header)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user