Construction Boba AI

Boba is an experimental AI co-pilot for product technique & generative ideation,
designed to enhance the ingenious ideation procedure. It’s an LLM-powered
software that we’re development to be told about:

An AI co-pilot refers to a man-made intelligence-powered assistant designed
to assist customers with more than a few duties, ceaselessly offering steering, strengthen, and automation
in several contexts. Examples of its software come with navigation programs,
virtual assistants, and instrument building environments. We love to think about a co-pilot
as an efficient spouse {that a} person can collaborate with to accomplish a selected area
of duties.

Boba as an AI co-pilot is designed to enhance the early phases of technique ideation and
idea era, which depend closely on speedy cycles of divergent
considering (often referred to as generative ideation). We in most cases put into effect generative ideation
by way of intently participating with our friends, consumers and subject material professionals, in order that we will
formulate and check cutting edge concepts that deal with our consumers’ jobs, pains and good points.
This begs the query, what if AI may additionally take part in the similar procedure? What if we
may generate and overview extra and higher concepts, sooner in partnership with AI? Boba begins to
permit this by way of the use of OpenAI’s LLM to generate concepts and resolution questions
that may assist scale and boost up the ingenious considering procedure. For the primary prototype of
Boba, we made up our minds to concentrate on rudimentary variations of the next features:

1. Analysis indicators and developments: Seek the internet for
articles and information that will help you resolution qualitative analysis questions,

2. Ingenious Matrix: The ingenious matrix is a concepting approach for
sparking new concepts on the intersections of distinct classes or
dimensions. This comes to pointing out a strategic steered, ceaselessly as a “How may
we” query, after which answering that query for each and every
aggregate/permutation of concepts on the intersection of each and every measurement. For

3. State of affairs development: State of affairs development is a means of
producing future-oriented tales by way of researching indicators of trade in
trade, tradition, and era. Eventualities are used to socialise learnings
in a contextualized narrative, encourage divergent product considering, behavior
resilience/desirability checking out, and/or tell strategic making plans. For
instance, you’ll steered Boba with the next and get a collection of destiny
situations in accordance with other time horizons and ranges of optimism and

4. Technique ideation: The usage of the Taking part in to Win technique
framework, brainstorm “the place to play” and ” win” alternatives
in accordance with a strategic steered and imaginable destiny situations. For instance you
can steered it with:

5. Thought era: According to a strategic steered, equivalent to a “how may we” query, generate
a couple of product or function ideas, which come with worth proposition pitches and hypotheses to check.

6. Storyboarding: Generate visible storyboards in accordance with a easy
steered or detailed narrative in accordance with present or destiny state situations. The
key options are:

The usage of Boba

Boba is a internet software that mediates an interplay between a human
person and a Massive-Language Type, lately GPT 3.5. A easy internet
front-end to an LLM simply provides the power for the person to speak with
the LLM. That is useful, however manner the person must discover ways to
successfully engage the LLM. Even within the couple of minutes that LLMs have seized
the general public pastime, we now have realized that there’s really extensive ability to
establishing the activates to the LLM to get an invaluable resolution, leading to
the perception of a “Suggested Engineer”. A co-pilot software like Boba provides
a spread of UI components that construction the dialog. This permits a person
to make naive activates which the applying can manipulate, enriching
easy requests with components that may yield a greater reaction from the

Boba can assist with a lot of product technique duties. We would possibly not
describe all of them right here, simply sufficient to offer a way of what Boba does and
to supply context for the patterns later within the article.

When a person navigates to the Boba software, they see an preliminary
display very similar to this

The left panel lists the more than a few product technique duties that Boba
helps. Clicking on the sort of adjustments the principle panel to the UI for
that job. For the remainder of the screenshots, we will forget about that job panel
at the left.

The above screenshot seems on the situation design job. This invitations
the person to go into a steered, equivalent to “Display me the way forward for retail”.

The UI provides a lot of drop-downs along with the steered, permitting
the person to indicate time-horizons and the character of the prediction. Boba
will then ask the LLM to generate situations, the use of Templated Suggested to counterpoint the person’s steered
with further components each from normal wisdom of the situation
development job and from the person’s picks within the UI.

Boba receives a Structured Reaction from the LLM and presentations the
outcome as set of UI components for each and every situation.

The person can then take the sort of situations and hit the discover
button, mentioning a brand new panel with an extra steered to have a Contextual Dialog with Boba.

Boba takes this steered and enriches it to concentrate on the context of the
decided on situation prior to sending it to the LLM.

Boba makes use of Make a selection and Raise Context
to carry onto the more than a few portions of the person’s interplay
with the LLM, permitting the person to discover in a couple of instructions with out
having to fret about supplying the correct context for each and every interplay.

Some of the difficulties with the use of an
LLM is that it is skilled best on information up to a few level prior to now, making
them useless for operating with up-to-date knowledge. Boba has a
function referred to as analysis indicators that makes use of Embedded Exterior Wisdom
to mix the LLM with common seek
amenities. It takes the induced analysis question, equivalent to “How is the
lodge business the use of generative AI as of late?”, sends an enriched model of
that question to a seek engine, retrieves the urged articles, sends
each and every article to the LLM to summarize.

That is an instance of the way a co-pilot software can maintain
interactions that contain actions that an LLM on my own is not appropriate for. No longer
simply does this supply up-to-date knowledge, we will additionally be sure we
supply supply hyperlinks to the person, and the ones hyperlinks would possibly not be hallucinations
(so long as the quest engine is not participating of the flawed mushrooms).

Some patterns for development generative co-pilot packages

In development Boba, we learnt so much about other patterns and approaches
to mediating a dialog between a person and an LLM, particularly Open AI’s
GPT3.5/4. This checklist of patterns isn’t exhaustive and is proscribed to the teachings
we now have learnt up to now whilst development Boba.

Templated Suggested

Use a textual content template to counterpoint a steered with context and construction

The primary and most simple development is the use of a string templates for the activates, additionally
referred to as chaining. We use Langchain, a library that gives a regular
interface for chains and end-to-end chains for not unusual packages out of
the field. Should you’ve used a Javascript templating engine, equivalent to Nunjucks,
EJS or Handlebars prior to, Langchain supplies simply that, however is designed particularly for
not unusual steered engineering workflows, together with options for serve as enter variables,
few-shot steered templates, steered validation, and extra subtle composable chains of activates.

For instance, to brainstorm attainable destiny situations in Boba, you’ll
input a strategic steered, equivalent to “Display me the way forward for bills” or perhaps a
easy steered just like the title of an organization. The person interface seems like

The steered template that powers this era seems one thing like

You're a visionary futurist. Given a strategic steered, you are going to create
{num_scenarios} futuristic, hypothetical situations that occur
{time_horizon} from now. Every situation should be a {optimism} model of the
destiny. Every situation should be {realism}.

Strategic steered: {strategic_prompt}

As you’ll believe, the LLM’s reaction will best be as just right because the steered
itself, so that is the place the desire for just right steered engineering is available in.
Whilst this text isn’t supposed to be an creation to steered
engineering, you are going to realize some tactics at play right here, equivalent to beginning
by way of telling the LLM to Undertake a
particularly that of a visionary futurist. This was once a method we trusted
widely in more than a few portions of the applying to supply extra related and
helpful completions.

As a part of our test-and-learn steered engineering workflow, we discovered that
iterating at the steered without delay in ChatGPT provides the shortest trail from
thought to experimentation and is helping construct self belief in our activates briefly.
Having stated that, we additionally discovered that we spent far more time at the person
interface (about 80%) than the AI itself (about 20%), particularly in
engineering the activates.

We additionally stored our steered templates so simple as imaginable, devoid of
conditional statements. Once we had to greatly adapt the steered based totally
at the person enter, equivalent to when the person clicks “Upload main points (indicators,
threats, alternatives)”, we made up our minds to run a distinct steered template
altogether, within the pastime of maintaining our steered templates from changing into
too advanced and difficult to deal with.

Structured Reaction

Inform the LLM to reply in a structured information layout

Virtually any software you construct with LLMs will possibly want to parse
the output of the LLM to create some structured or semi-structured information to
additional function on on behalf of the person. For Boba, we needed to paintings with
JSON up to imaginable, so we attempted many various permutations of having
GPT to go back well-formed JSON. We have been reasonably stunned by way of how effectively and
persistently GPT returns well-formed JSON in accordance with the directions in our
activates. For instance, right here’s what the situation era reaction
directions may seem like:

You're going to reply with just a legitimate JSON array of situation gadgets.
Every situation object can have the next schema:
    "name": <string>,       //Will have to be a whole sentence written prior to now traumatic
    "abstract": <string>,   //State of affairs description
    "plausibility": <string>,  //Plausibility of situation
    "horizon": <string>

We have been similarly stunned by way of the truth that it would strengthen relatively advanced
nested JSON schemas, even if we described the reaction schemas in pseudo-code.
Right here’s an instance of the way we may describe a nested reaction for technique

You're going to reply in JSON layout containing two keys, "questions" and "methods", with the respective schemas under:
    "questions": [<list of question objects, with each containing the following keys:>]
      "query": <string>,           
      "resolution": <string>             
    "methods": [<list of strategy objects, with each containing the following keys:>]
      "name": <string>,               
      "abstract": <string>,             
      "problem_diagnosis": <string>, 
      "winning_aspiration": <string>,   
      "where_to_play": <string>,        
      "how_to_win": <string>,           
      "assumptions": <string>          

A fascinating facet impact of describing the JSON reaction schema was once that we
may additionally nudge the LLM to supply extra related responses within the output. For
instance, for the Ingenious Matrix, we wish the LLM to take into accounts many various
dimensions (the steered, the row, the columns, and each and every concept that responds to the
steered on the intersection of each and every row and column):

By means of offering a few-shot steered that features a explicit instance of the output
schema, we have been ready to get the LLM to “assume” in the correct context for each and every
thought (the context being the steered, row and column):

You're going to reply with a legitimate JSON array, by way of row by way of column by way of thought. For instance:

If Rows = "row 0, row 1" and Columns = "column 0, column 1" then you are going to reply
with the next:

    "row": "row 0",
    "columns": [
        "column": "column 0",
        "ideas": [
            "title": "Idea 0 title for prompt and row 0 and column 0",
            "description": "idea 0 for prompt and row 0 and column 0"
        "column": "column 1",
        "concepts": [
            "title": "Idea 0 title for prompt and row 0 and column 1",
            "description": "idea 0 for prompt and row 0 and column 1"
    "row": "row 1",
    "columns": [
        "column": "column 0",
        "ideas": [
            "title": "Idea 0 title for prompt and row 1 and column 0",
            "description": "idea 0 for prompt and row 1 and column 0"
        "column": "column 1",
        "concepts": [
            "title": "Idea 0 title for prompt and row 1 and column 1",
            "description": "idea 0 for prompt and row 1 and column 1"

We will have then again described the schema extra succinctly and
typically, however by way of being extra elaborate and explicit in our instance, we
effectively nudged the standard of the LLM’s reaction within the path we
sought after. We imagine it’s because LLMs “assume” in tokens, and outputting (ie
repeating) the row and column values prior to outputting the information supplies extra
correct context for the information being generated.

On the time of this writing, OpenAI has launched a brand new function referred to as
Serve as
, which
supplies a distinct manner to reach the objective of formatting responses. On this
manner, a developer can describe callable serve as signatures and their
respective schemas as JSON, and feature the LLM go back a serve as name with the
respective parameters equipped in JSON that conforms to that schema. That is
in particular helpful in situations when you wish to have to invoke exterior gear, equivalent to
acting a internet seek or calling an API in line with a steered. Langchain
additionally supplies identical capability, however I believe they’ll quickly supply local
integration between their exterior gear API and the OpenAI serve as calling

Actual-Time Development

Circulate the reaction to the UI so customers can track development

Some of the first few stuff you’ll notice when enforcing a graphical
person interface on peak of an LLM is that looking ahead to all the reaction to
whole takes too lengthy. We don’t realize this as a lot with ChatGPT as a result of
it streams the reaction personality by way of personality. That is crucial person
interplay development to remember as a result of, in our revel in, a person can
best wait on a spinner for goodbye prior to dropping persistence. In our case, we
didn’t need the person to attend quite a lot of seconds prior to they began
seeing a reaction, although it was once a partial one.

Therefore, when enforcing a co-pilot revel in, we extremely suggest
appearing real-time development all through the execution of activates that take extra
than about a seconds to finish. In our case, this supposed streaming the
generations around the complete stack, from the LLM again to the UI in real-time.
Thankfully, the Langchain and OpenAI APIs give you the talent to do exactly

const chat = new ChatOpenAI({
  temperature: 1,
  modelName: 'gpt-3.5-turbo',
  streaming: true,
  callbackManager: onTokenStream ?
      async handleLLMNewToken(token) {
    }) : undefined

This allowed us to give you the real-time development had to create a smoother
revel in for the person, together with the power to prevent a era
mid-completion if the information being generated didn’t fit the person’s

On the other hand, doing so provides numerous further complexity for your software
good judgment, particularly at the view and controller. In terms of Boba, we additionally had
to accomplish best-effort parsing of JSON and deal with temporal state all through the
execution of an LLM name. On the time of penning this, some new and promising
libraries are popping out that make this more straightforward for internet builders. For instance,
the Vercel AI SDK is a library for development
edge-ready AI-powered streaming textual content and chat UIs.

Make a selection and Raise Context

Seize and upload related context knowledge to next motion

Some of the largest obstacles of a talk interface is {that a} person is
restricted to a single-threaded context: the dialog chat window. When
designing a co-pilot revel in, we advise considering deeply about
design UX affordances for acting movements inside the context of a
variety, very similar to our herbal inclination to indicate at one thing in genuine
lifestyles within the context of an motion or description.

Make a selection and Raise Context permits the person to slim or develop the scope of
interplay to accomplish next duties – often referred to as the duty context. That is in most cases
executed by way of settling on a number of components within the person interface after which acting an motion on them.
In terms of Boba, as an example, we use this development to permit the person to have
a narrower, centered dialog about an concept by way of settling on it (eg a situation, technique or
prototype idea), in addition to to choose and generate permutations of a
idea. First, the person selects an concept (both explicitly with a checkbox or implicitly by way of clicking a hyperlink):

Then, when the person plays an motion at the variety, the chosen merchandise(s) are carried over as context into the brand new job,
as an example as situation subprompts for technique era when the person clicks “Brainstorm methods and questions for this situation”,
or as context for a herbal language dialog when the person clicks Discover:

Relying at the nature and period of the context
you need to identify for a phase of dialog/interplay, enforcing
Make a selection and Raise Context will also be anyplace from really easy to very tough. When
the context is short and will have compatibility right into a unmarried LLM context window (the utmost
measurement of a steered that the LLM helps), we will put into effect it via steered
engineering on my own. For instance, in Boba, as proven above, you’ll click on “Discover”
on an concept and feature a dialog with Boba about that concept. The best way we
put into effect this within the backend is to create a multi-message chat

const chatPrompt = ChatPromptTemplate.fromPromptMessages([
const formattedPrompt = look ahead to chatPrompt.formatPromptValue({
  enter: enter

Any other method of enforcing Make a selection and Raise Context is to take action inside of
the steered by way of offering the context inside of tag delimiters, as proven under. In
this situation, the person has decided on a couple of situations and desires to generate
methods for the ones situations (a method ceaselessly utilized in situation development and
tension checking out of concepts). The context we wish to raise into the method
era is selection of decided on situations:

Your questions and methods should be explicit to figuring out the next
attainable destiny situations (if any)

On the other hand, when your context outgrows an LLM’s context window, or if you wish to have
to supply a extra subtle chain of previous interactions, you might have to
hotel to the use of exterior momentary reminiscence, which in most cases comes to the use of a
vector retailer (in-memory or exterior). We’ll give an instance of do
one thing identical in Embedded Exterior Wisdom.

If you wish to study extra concerning the efficient use of variety and
context in generative packages, we extremely suggest a chat given by way of
Linus Lee, of Perception, on the LLMs in Manufacturing convention: “Generative Studies Past Chat”.

Contextual Dialog

Permit direct dialog with the LLM inside of a context.

This can be a particular case of Make a selection and Raise Context.
Whilst we needed Boba to damage out of the chat window interplay style
up to imaginable, we discovered that it’s nonetheless very helpful to give you the
person a “fallback” channel to speak without delay with the LLM. This permits us
to supply a conversational revel in for interactions we don’t strengthen in
the UI, and strengthen instances when having a textual herbal language
dialog does take advantage of sense for the person.

Within the instance under, the person is talking to Boba a couple of idea for
customized spotlight reels equipped by way of Rogers Sportsnet. The whole
context is discussed as a talk message (“On this idea, Find a international of
sports activities you like…”), and the person has requested Boba to create a person adventure for
the concept that. The reaction from the LLM is formatted and rendered as Markdown:

When designing generative co-pilot studies, we extremely suggest
supporting contextual conversations together with your software. Be sure to
be offering examples of helpful messages the person can ship for your software so
they know what sort of conversations they are able to have interaction in. In terms of
Boba, as proven within the screenshot above, the ones examples are presented as
message templates beneath the enter field, equivalent to “Are you able to be extra

Out-Loud Pondering

Inform LLM to generate intermediate effects whilst answering

Whilst LLMs don’t if truth be told “assume”, it’s value considering metaphorically
a couple of word by way of Andrei Karpathy of OpenAI: “LLMs ‘assume’ in
What he manner by way of this
is that GPTs generally tend to make extra reasoning mistakes when making an attempt to respond to a
query instantly, as opposed to while you give them extra time (i.e. extra tokens)
to “assume”. In development Boba, we discovered that the use of Chain of Concept (CoT)
prompting, or extra particularly, soliciting for a series of reasoning prior to an
resolution, helped the LLM to reason why its manner towards higher-quality and extra
related responses.

In some portions of Boba, like technique and idea era, we ask the
LLM to generate a collection of questions that increase at the person’s enter steered
prior to producing the information (methods and ideas on this case).

Whilst we show the questions generated by way of the LLM, an similarly efficient
variant of this development is to put into effect an interior monologue that the person is
now not uncovered to. On this case, we’d ask the LLM to assume via their
reaction and put that interior monologue right into a separate a part of the reaction, that
we will parse out and forget about within the effects we display to the person. A extra elaborate
description of this development will also be present in OpenAI’s GPT Highest Practices
, within the
phase Give GPTs time to

As a person revel in development for generative packages, we discovered it useful
to proportion the reasoning procedure with the person, anyplace suitable, in order that the
person has further context to iterate at the subsequent motion or steered. For
instance, in Boba, figuring out the sorts of questions that Boba considered provides the
person extra concepts about divergent spaces to discover, or to not discover. It additionally
permits the person to invite Boba to exclude sure categories of concepts within the subsequent
iteration. Should you do pass down this trail, we advise making a UI affordance
for hiding a monologue or chain of concept, equivalent to Boba’s function to toggle
examples proven above.

Iterative Reaction

Supply affordances for the person to have a back-and-forth
interplay with the co-pilot

LLMs are sure to both misunderstand the person’s intent or just
generate responses that don’t meet the person’s expectancies. Therefore, so is
your generative software. One of the robust features that
distinguishes ChatGPT from conventional chatbots is the power to flexibly
iterate on and refine the path of the dialog, and therefore support
the standard and relevance of the responses generated.

In a similar fashion, we imagine that the standard of a generative co-pilot
revel in relies on the power of a person to have a fluid back-and-forth
interplay with the co-pilot. That is what we name the Iterate on Reaction
development. It will contain a number of approaches:

  • Correcting the unique enter equipped to the applying/LLM
  • Refining part of the co-pilot’s reaction to the person
  • Offering comments to nudge the applying in a distinct path

One instance of the place we’ve carried out Iterative Reaction
Boba is in Storyboarding. Given a steered (both transient or elaborate), Boba
can generate a visible storyboard, which incorporates a couple of scenes, with each and every
scene having a story script and a picture generated with Strong
Diffusion. For instance, under is a partial storyboard describing the revel in of a
“Resort of the Long term”:

Since Boba makes use of the LLM to generate the Strong Diffusion steered, we don’t
understand how just right the pictures will prove–so it’s a bit of of a hit and miss with
this option. To make amends for this, we made up our minds to give you the person the
talent to iterate at the symbol steered in order that they are able to refine the picture for
a given scene. The person would do that by way of merely clicking at the symbol,
updating the Strong Diffusion steered, and urgent Accomplished, upon which Boba
would generate a brand new symbol with the up to date steered, whilst holding the
remainder of the storyboard:

Any other instance Iterative Reaction that we
are lately operating on is a function for the person to supply comments
to Boba at the high quality of concepts generated, which might be a mix
of Make a selection and Raise Context and Iterative Reaction. One
manner can be to offer a thumbs up or thumbs down on an concept, and
letting Boba incorporate that comments into a brand new or subsequent set of
suggestions. Any other manner can be to supply conversational
comments within the type of herbal language. Both manner, we want to
do that in a method that helps reinforcement finding out (the information get
higher as you supply extra comments). A just right instance of this could be
Github Copilot, which demotes code tips which have been not noted by way of
the person in its score of subsequent ideal code tips.

We imagine that this is without doubt one of the maximum necessary, albeit
generically-framed, patterns to enforcing efficient generative
studies. The difficult section is incorporating the context of the
comments into next responses, which is able to ceaselessly require enforcing
momentary or long-term reminiscence for your software on account of the restricted
measurement of context home windows.

Embedded Exterior Wisdom

Mix LLM with different knowledge resources to get right of entry to information past
the LLM’s coaching set

As alluded to previous on this article, oftentimes your generative
packages will want the LLM to include exterior gear (equivalent to an API
name) or exterior reminiscence (momentary or long-term). We bumped into this
situation after we have been enforcing the Analysis function in Boba, which
permits customers to respond to qualitative analysis questions in accordance with publicly
to be had knowledge on the net, as an example “How is the lodge business
the use of generative AI as of late?”:

To put into effect this, we needed to “equip” the LLM with Google as an exterior
internet seek device and provides the LLM the power to learn probably lengthy
articles that won’t have compatibility into the context window of a steered. We additionally
sought after Boba so as to chat with the person about any related articles the
person reveals, which required enforcing a type of momentary reminiscence. Finally,
we needed to give you the person with right kind hyperlinks and references that have been
used to respond to the person’s analysis query.

The best way we carried out this in Boba is as follows:

  1. Use a Google SERP API to accomplish the internet seek in accordance with the person’s question
    and get the highest 10 articles (seek effects)
  2. Learn the entire content material of each and every article the use of the Extract API
  3. Save the content material of each and every article in momentary reminiscence, particularly an
    in-memory vector retailer. The embeddings for the vector retailer are generated the use of
    the OpenAI API, and in accordance with chunks of each and every article (as opposed to embedding all the
    article itself).
  4. Generate an embedding of the person’s seek question
  5. Question the vector retailer the use of the embedding of the quest question
  6. Suggested the LLM to respond to the person’s authentic question in herbal language,
    whilst prefixing the result of the vector retailer question as context into the LLM

This may occasionally sound like numerous steps, however that is the place the use of a device like
Langchain can accelerate your procedure. Particularly, Langchain has an
end-to-end chain referred to as VectorDBQAChain, and the use of that to accomplish the
question-answering took just a few strains of code in Boba:

const researchArticle = async (article, steered) => {
  const style = new OpenAI({});
  const textual content = article.textual content;
  const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
  const doctors = look ahead to textSplitter.createDocuments([text]);
  const vectorStore = look ahead to HNSWLib.fromDocuments(doctors, new OpenAIEmbeddings());
  const chain = VectorDBQAChain.fromLLM(style, vectorStore);
  const res = look ahead to{
    input_documents: doctors,
    question: steered + ". Be detailed for your reaction.",
  go back { research_answer: res.textual content };

The item textual content accommodates all the content material of the thing, which won’t
have compatibility inside of a unmarried steered. So we carry out the stairs described above. As you’ll
see, we used an in-memory vector retailer referred to as HNSWLib (Hierarchical Navigable
Small Global). HNSW graphs are some of the top-performing indexes for vector
similarity seek. On the other hand, for higher scale use instances and/or long-term reminiscence,
we advise the use of an exterior vector DB like Pinecone or Weaviate.

We additionally will have additional streamlined our workflow by way of the use of Langchain’s
exterior gear API to accomplish the Google seek, however we made up our minds in opposition to it
as it offloaded an excessive amount of determination making to Langchain, and we have been getting
combined, sluggish and harder-to-parse effects. Any other option to enforcing
exterior gear is to make use of Open AI’s lately launched Serve as Calling
, which we
discussed previous on this article.

To summarize, we mixed two distinct tactics to put into effect Embedded Exterior Wisdom:

  1. Use Exterior Device: Seek and skim articles the use of Google SERP and Extract
  2. Use Exterior Reminiscence: Brief-term reminiscence the use of an in-memory vector retailer

Like this post? Please share to your friends:
Leave a Reply

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: