Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/assets/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@
column-gap: 20px;
font-size: 16px;
}

#searches-nav {
display: flex;
justify-content: center;
align-items: center;
column-gap: 20px;
}
10 changes: 10 additions & 0 deletions app/graphql/contacts/find.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
query contacts_find($id: ID!) {
records(per_page: 1, filter: { id: { value: $id } }) {
results {
id
created_at
body: property(name: "body")
email: property(name: "email")
}
}
}
21 changes: 21 additions & 0 deletions app/lib/consumers/contact_created/create_embedding.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% liquid
function contact = 'queries/contacts/find', id: event.id
log contact, type: 'contact'

function response = 'modules/openai/commands/openai/fetch_embeddings', object: contact.body
log response, type: 'response'

if response.error == blank
assign pos_embedding_input = '{}' | parse_json
assign metadata = '{}' | parse_json

hash_assign metadata['contact_id'] = contact.id
hash_assign pos_embedding_input['metadata'] = metadata
hash_assign pos_embedding_input['embedding'] = response.data.first.embedding
hash_assign pos_embedding_input['content'] = contact.body
function pos_embedding = 'modules/openai/commands/embeddings/create', object: pos_embedding_input
log pos_embedding, type: 'pos_embedding'
endif
%}


9 changes: 9 additions & 0 deletions app/lib/queries/contacts/find.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% liquid
if id == null
log "contacts/find requires ID", type: "ERROR"
endif

graphql res = 'contacts/find', id: id

return res.records.results.first
%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

{% liquid
comment
populate_embeddings_for_existing_contacts migration code goes below
endcomment
%}

3 changes: 2 additions & 1 deletion app/pos-modules.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"modules": {
"core": "2.0.7",
"common-styling": "1.32.0",
"user": "5.1.1"
"user": "5.1.1",
"openai": "1.1.0"
}
}
3 changes: 2 additions & 1 deletion app/pos-modules.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"modules": {
"core": "2.0.7",
"common-styling": "1.32.0",
"user": "5.1.1"
"user": "5.1.1",
"openai": "1.1.0"
}
}
9 changes: 9 additions & 0 deletions app/views/pages/admin/contacts/ai_search.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% liquid
if context.params.query != blank
function response = 'modules/openai/commands/openai/fetch_embeddings', object: context.params.query

function related_embeddings = 'modules/openai/queries/embeddings/search', related_to: response.data.first.embedding, limit: 3, metadata: null
endif

render 'admin/contacts/ai_results', embeddings: related_embeddings, response: response
%}
32 changes: 32 additions & 0 deletions app/views/partials/admin/contacts/ai_results.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{% render 'admin/contacts/nav' %}

<h1 class="pos-heading-1">AI Search results</h1>
<div class="pos-card">
<p>OpenAI Response:</p>
<pre>
<code>
{{ response }}
</code>
</pre>
</div>
<section class="pos-table">
<header>
<div>ID</div>
<div>Body</div>
</header>
<div class="pos-table-content pos-card">

{% for embedding in embeddings.results %}
<ul>
<li>
<span class="pos-table-content-heading">ID</span>
{{ embedding.metadata.contact_id }}
</li>
<li>
<span class="pos-table-content-heading">Body</span>
<span title="{{ embedding.content }}">{{ embedding.content | truncate: 40 }}</span>
</li>
</ul>
{% endfor %}
</div>
</section>
26 changes: 26 additions & 0 deletions app/views/partials/admin/contacts/nav.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<div id="searches-nav">
<div class="pos-card">
<form action='/admin' method="GET" >
<fieldset class="pos-form-fieldset-combined">
<input type="text" name="keyword" placeholder="Search" class="pos-form-input" value="{{ context.params.keyword }}">
<button type="submit" class="pos-button">
<span class="pos-label">Search</span>
{% render 'modules/common-styling/icon', icon: 'search' %}
</button>
</fieldset>
</form>
</div>

<div class="pos-card">
<form action="/admin/contacts/ai_search" method="GET">
<fieldset class="pos-form-fieldset-combined">
<input type="text" name="query" placeholder="AI Search" class="pos-form-input" value="{{ context.params.query }}">
<button type="submit" class="pos-button">
<span class="pos-label">AI Search</span>
{% render 'modules/common-styling/icon', icon: 'search' %}
</button>
</fieldset>
</form>
</div>

</div>
12 changes: 1 addition & 11 deletions app/views/partials/admin/index.liquid
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
<div class="pos-card">
<form method="GET" >
<fieldset class="pos-form-fieldset-combined">
<input type="text" name="keyword" placeholder="Search" class="pos-form-input" value="{{ context.params.keyword }}">
<button type="submit" class="pos-button">
<span class="pos-label">Search</span>
{% render 'modules/common-styling/icon', icon: 'search' %}
</button>
</fieldset>
</form>
</div>
{% render 'admin/contacts/nav' %}
<h1 class="pos-heading-1">Contacts</h1>
<section class="pos-table">
<header>
Expand Down
11 changes: 11 additions & 0 deletions modules/openai/public/api_calls/chat.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
to: >
https://api.openai.com/{{ context.constants['modules/openai/OPENAI_VERSION'] | default: "v1" }}/chat/completions
request_type: POST
headers: >
{
"Authorization": "Bearer {{ context.constants['modules/openai/OPENAI_SECRET_TOKEN'] }}",
"Content-Type": "application/json"
}
---
{{ data }}
11 changes: 11 additions & 0 deletions modules/openai/public/api_calls/responses.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
to: >
https://api.openai.com/{{ context.constants['modules/openai/OPENAI_VERSION'] | default: "v1" }}/responses
request_type: POST
headers: >
{
"Authorization": "Bearer {{ context.constants['modules/openai/OPENAI_SECRET_TOKEN'] }}",
"Content-Type": "application/json"
}
---
{{ data }}
17 changes: 17 additions & 0 deletions modules/openai/public/graphql/embeddings/create.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
mutation embedding_create($embedding: [Float!]!, $content: String!, $metadata: HashObject, $token_count: Int){
embedding_create: embedding_create_rc(
embedding: {
embedding: $embedding
content: $content
metadata: $metadata
token_count: $token_count
}
)
{
id
embedding
content
metadata
token_count
}
}
7 changes: 7 additions & 0 deletions modules/openai/public/graphql/embeddings/delete.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mutation embedding_delete($id: ID!){
embedding_delete: embedding_delete_rc(id: $id){
id
content
metadata
}
}
27 changes: 27 additions & 0 deletions modules/openai/public/graphql/embeddings/search.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
query embeddings($limit: Int = 2000, $page: Int = 1, $metadata: [JsonbFilter!], $related_to: [Float!]) {
embeddings: embeddings_rc(
per_page: $limit,
page: $page
filter: { metadata: $metadata }
sort: {
embedding: {
order: euclidean
embedding: $related_to
}
}

)
{
total_entries
has_next_page
has_previous_page
total_pages
results {
id
metadata
embedding
content
token_count
}
}
}
18 changes: 18 additions & 0 deletions modules/openai/public/graphql/embeddings/update.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
mutation embedding_update($id: ID!, $embedding: [Float!]!, $content: String!, $metadata: HashObject, $token_count: Int){
embedding_update: embedding_update_rc(
id: $id
embedding: {
embedding: $embedding
content: $content
metadata: $metadata
token_count: $token_count
}
)
{
id
embedding
content
metadata
token_count
}
}
11 changes: 11 additions & 0 deletions modules/openai/public/lib/commands/embeddings/create.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% liquid
function object = 'modules/openai/commands/embeddings/create/build', object: object
function object = 'modules/openai/commands/embeddings/create/check', object: object

if object.valid
function object = 'modules/openai/commands/embeddings/create/execute', object: object
endif

return object
%}

10 changes: 10 additions & 0 deletions modules/openai/public/lib/commands/embeddings/create/build.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% liquid
assign embedding = '{}' | parse_json

hash_assign embedding['embedding'] = object.embedding
hash_assign embedding['content'] = object.content
hash_assign embedding['metadata'] = object.metadata
hash_assign embedding['token_count'] = object.token_count

return embedding
%}
11 changes: 11 additions & 0 deletions modules/openai/public/lib/commands/embeddings/create/check.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% liquid
assign c = '{ "errors": {}, "valid": true }' | parse_json

function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'embedding'
function c = 'modules/core/validations/length', c: c, object: object, field_name: 'embedding', is: 1536
function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'content'

assign object = object | hash_merge: c

return object
%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% liquid
graphql r = 'modules/openai/embeddings/create', args: object

assign object = r.embedding_create
hash_assign object['valid'] = true

return object
%}

12 changes: 12 additions & 0 deletions modules/openai/public/lib/commands/embeddings/delete.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% liquid

function object = 'modules/openai/commands/embeddings/delete/build', object: object, id: id
function object = 'modules/openai/commands/embeddings/delete/check', object: object

if object.valid
function object = 'modules/core/commands/execute', mutation_name: 'modules/openai/embeddings/delete', object: object, selection: 'embedding_delete'
endif

return object
%}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% liquid
assign id = id | default: object.id
assign embedding = '{}' | parse_json
hash_assign embedding['id'] = id

return embedding
%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% liquid
assign c = '{ "errors": {}, "valid": true }' | parse_json

function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'

assign object = object | hash_merge: c

return object
%}
11 changes: 11 additions & 0 deletions modules/openai/public/lib/commands/embeddings/update.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% liquid
function object = 'modules/openai/commands/embeddings/update/build', object: object, id: id
function object = 'modules/openai/commands/embeddings/update/check', object: object

if object.valid
function object = 'modules/openai/commands/embeddings/update/execute', object: object
endif

return object
%}

13 changes: 13 additions & 0 deletions modules/openai/public/lib/commands/embeddings/update/build.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% liquid
assign id = id | default: object.id

assign embedding = '{}' | parse_json
hash_assign embedding['id'] = id

hash_assign embedding['embedding'] = object.embedding
hash_assign embedding['content'] = object.content
hash_assign embedding['metadata'] = object.metadata
hash_assign embedding['token_count'] = object.token_count

return embedding
%}
12 changes: 12 additions & 0 deletions modules/openai/public/lib/commands/embeddings/update/check.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% liquid
assign c = '{ "errors": {}, "valid": true }' | parse_json

function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'id'
function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'embedding'
function c = 'modules/core/validations/length', c: c, object: object, field_name: 'embedding', is: 1536
function c = 'modules/core/validations/presence', c: c, object: object, field_name: 'content'

assign object = object | hash_merge: c

return object
%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% liquid
graphql r = 'modules/openai/embeddings/update', args: object

assign object = r.embedding_update
hash_assign object['valid'] = true

return object
%}

Loading